🖥 Scoped Values в Java (Часть 2)



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