Класс ClassValue<T>

public abstract class ClassValue<T>
extends Object

Лениво связывает вычисленное значение с (потенциально) каждым типом. Например, если динамическому языку необходимо построить таблицу диспетчеризации сообщений для каждого класса, встреченного в месте вызова сообщения, он может использовать ClassValue, чтобы кэшировать информацию, необходимую для быстрого выполнения отправки сообщения для каждого встреченного класса.

Since:
1.7

Конструкторы

МодификаторКонструкторОписание
protected ClassValue()

Единственный конструктор.

Методы

Модификатор и типМетодОписание
protected abstract TcomputeValue​(Class<?> type)

Вычисляет производное значение данного класса для этого ClassValue.

Tget​(Class<?> type)

Возвращает значение для данного класса.

voidremove​(Class<?> type)

Удаляет связанное значение для данного класса.

Методы, объявленные в классе java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Конструкторы

ClassValue

protected ClassValue()

Единственный конструктор. (Для вызова конструкторами подклассов, как правило, неявным.)

Методы

computeValue

protected abstract T computeValue(Class<?> type)

Вычисляет производное значение данного класса для этого ClassValue.

Этот метод будет вызван в первом потоке, который получает доступ к значению с помощью метода get.

В нормальных условиях этот метод вызывается не более одного раза на класс, но он может быть вызван снова, если был сделан вызов remove.

Если этот метод вызывает исключение, соответствующий вызов get завершится аномально с этим исключением, и значение класса не будет записано.

Parameters:
type - тип, значение класса которого необходимо вычислить
Returns:
нововычисленное значение, связанное с этим ClassValue, для данного класса или интерфейса
See Also:
get(java.lang.Class<?>), remove(java.lang.Class<?>)

get

public T get(Class<?> type)

Возвращает значение для данного класса. Если значение еще не было вычислено, оно получается путём вызова метода computeValue.

Фактическое размещение значения в классе выполняется атомарно. В этот момент, если несколько конкурирующих потоков вычислили значения, выбирается одно, и возвращается всем конкурирующим потокам.

Параметр type обычно представляет собой класс, но он может представлять любой тип, например, интерфейс, примитивный тип (такой как int.class) или void.class.

В отсутствие вызовов remove, значение класса имеет простую диаграмму состояний: неинициализированное и инициализированное. При выполнении вызовов remove, правила наблюдения за значением более сложные. См. документацию по remove для получения дополнительной информации.

Parameters:
type - тип, значение класса которого необходимо вычислить или получить
Returns:
текущее значение, связанное с этим ClassValue, для данного класса или интерфейса
Throws:
NullPointerException - если аргумент равен null
See Also:
remove(java.lang.Class<?>), computeValue(java.lang.Class<?>)

remove

public void remove(Class<?> type)

Удаляет связанное значение для данного класса. Если это значение впоследствии читается для того же класса, его значение будет повторно инициализировано путём вызова метода computeValue. Это может привести к дополнительному вызову метода computeValue для данного класса.

Чтобы объяснить взаимодействие между вызовами get и remove, необходимо смоделировать переходы состояний значения класса, учитывая чередование неинициализированного и инициализированного состояний.

Когда поток T удаляет значение класса в состоянии 2N, ничего не происходит, так как значение класса уже неинициализировано. В противном случае состояние атомарно переходит в 2N+1.

Когда поток T запрашивает значение класса в состоянии 2N, поток сначала пытается инициализировать значение класса в состояние 2N+1 путём вызова computeValue и установки результирующего значения.

Когда T пытается установить нововычисленное значение, если состояние всё ещё равно 2N, значение класса будет инициализировано вычисленным значением, переведя его в состояние 2N+1.

В противном случае, вне зависимости от чётности или нечётности нового состояния, T отбросит нововычисленное значение и повторит операцию get.

Отбрасывание и повторный вызов являются важным условием, так как в противном случае T мог бы потенциально установить катастрофически устаревшее значение. Например:

  • T вызывает CV.get(C) и видит состояние 2N
  • T быстро вычисляет зависящее от времени значение V0 и готовится установить его
  • T попадает под влияние несчастливого события страниц или планирования и спит в течение длительного времени
  • ...в то время как T2 также вызывает CV.get(C) и видит состояние 2N
  • T2 быстро вычисляет аналогичное зависящее от времени значение V1 и устанавливает его на CV.get(C)
  • T2 (или третий поток) затем вызывает CV.remove(C), отменяя работу T2
  • предыдущие действия T2 повторяются несколько раз
  • также, соответствующие вычисленные значения меняются со временем: V1, V2, ...
  • ...в то время как T просыпается и пытается установить V0; это должно потерпеть неудачу
В вышеупомянутом сценарии можно предположить, что CV.computeValue использует блокировки для надлежащего наблюдения за зависящими от времени состояниями, когда он вычисляет V1 и т.д. Это не устраняет угрозу устаревшего значения, так как есть временной промежуток между возвратом computeValue в T и установкой нового значения. Никакая пользовательская синхронизация невозможна в течение этого времени.
Parameters:
type - тип, значение класса которого необходимо удалить
Throws:
NullPointerException - если аргумент равен null

© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ClassValue.html

Spec-Zone .ru
спецификации, руководства, описания, API