Spec-Zone.ru › OpenJDK 17

Класс ClassValue<T>

java.lang.Object
java.lang.ClassValue<T>
public abstract class ClassValue<T> extends Object
Лениво связывает вычисленное значение с (потенциально) каждым типом. Например, если динамичному языку необходимо создать таблицу диспетчеризации сообщений для каждого класса, встреченного в месте отправки сообщения, он может использовать ClassValue для кэширования информации, необходимой для быстрого отправки сообщения, для каждого встреченного класса.
Since:
1.7

Краткое описание конструкторов

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

Краткое описание методов

Модификатор и тип Метод Описание
protected abstract T computeValue(Class<?> type)
Вычисляет выведенное значение данного класса для этого ClassValue.
T get(Class<?> type)
Возвращает значение для данного класса.
void remove(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 завершится аномально с этим исключением, и значение класса не будет записано.

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

get

public T get(Class<?> type)
Возвращает значение для данного класса. Если значение еще не вычислено, оно получено путем вызова метода computeValue.

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

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

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

Параметры:
type - тип, значение класса которого необходимо вычислить или получить
Возвращает:
текущее значение, связанное с этим ClassValue, для данного класса или интерфейса
Исключения:
NullPointerException - если аргумент равен null
См. также:
  • 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 и установкой нового значения. Во время этого интервала никакой пользовательской синхронизации невозможна.
Параметры:
type - тип, значение класса которого необходимо удалить
Исключения:
NullPointerException - если аргумент равен null

© 1993, 2021, 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/17/docs/api/java.base/java/lang/ClassValue.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API