Недавно мы рассказывали про 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