Недавно мы рассказывали про Scoped Values. Одной из ключевых особенностей Scoped Values (JEP-481) является отсутствие метода
set, в отличие от ThreadLocal, что позволяет гарантировать, что после привязки значения к run/call методам конкретных Runnable и Callable, оно не может быть в них изменено:
private static final ScopedValue<String> X = ScopedValue.newInstance();
void foo() {
ScopedValue.runWhere(X, "hello", () -> bar()); //привязываем значение "hello" для метода bar()
}
void bar() {
System.out.println(X.get()); // "hello"
ScopedValue.runWhere(X, "goodbye", () -> baz()); //привязываем значение "goodbye" для метода baz()
System.out.println(X.get()); // "hello"
}
void baz() {
System.out.println(X.get()); // "goodbye"
}
1. В методе
foo() устанавливаем значение "hello" для области видимости внутри метода bar()2. В методе
bar() запрашиваем значение. Получаем "hello"3. В методе
bar() устанавливаем значение "goodbye" для области видимости внутри метода baz()4. В методе
bar() запрашиваем значение. Получаем "hello". Тем самым убеждаемся, что после установки значения для области видимости внутри метода baz() оно не поменялось для метода bar()5. В методе
baz() запрашиваем значение. Получаем "goodbye".Важно отметить, что привязка "goodbye" действует только внутри вложенной области видимости. После завершения выполнения метода
baz() значение X в bar() возвращается к "hello". Таким образом, тело метода bar() не может изменить привязку, видимую этим методом, но может изменить привязку, видимую его вызываемыми методами. После завершения метода foo() X возвращается в состояние без привязки. Такое вложение гарантирует ограниченный срок действия для совместного использования нового значения.Scoped Values API также предоставляет метод
callWhere, который позволяет получить результат выполнения:
var result = ScopedValue.callWhere(X, "hello", () -> bar());
В этом случае
callWhere выполняет код внутри области видимости, где X привязан к значению "hello", и возвращает результат выполнения.Подводя итог, складывается ощущение, что нововведение предоставляет более безопасный и эффективный способ передачи данных между потоками по сравнению с использованием
ThreadLocal. Однако с уверенностью можно будет об этом говорить только после того, как фича выйдет из preview и войдет в состав языка на постоянной основе.Ставьте 🔥 если разбор JEP был полезен и вы хотели бы видеть больше подобных обзоров
#Java #JEP