[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-java-11-25-scoped-values-zamena-threadlocal":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":16,"progress":17,"seo":18},411,"scoped-values-zamena-threadlocal",11,"java-11-25","Java 11–25","🆕","Scoped Values — замена ThreadLocal?","Scoped Values — механизм для передачи иммутабельных данных через стек вызовов без явной передачи параметров. Альтернатива `ThreadLocal`, разработанная специально для Virtual Threads — не создаёт копию на каждый поток и автоматически ограничивает время жизни.\n\n### ThreadLocal vs ScopedValue\n\n| Критерий | ThreadLocal | ScopedValue |\n|----------|------------|-------------|\n| Мутабельность | Мутабельный (`set()`) | Immutable (только `where().run()`) |\n| Время жизни | Пока не вызван `remove()` | Автоматически — ограничен `run()`\u002F`call()` |\n| Наследование | `InheritableThreadLocal` (копия) | Автоматическое наследование в child-scope |\n| Память | Копия на каждый поток | Разделяемая ссылка |\n| Virtual Threads | Проблема (миллион копий = OOM) | Оптимально |\n\n```java\n\u002F\u002F ThreadLocal — проблемы с Virtual Threads:\nprivate static final ThreadLocal\u003CUser> CURRENT_USER = new ThreadLocal\u003C>();\nCURRENT_USER.set(user);\n\u002F\u002F ... где-то в стеке вызовов:\nUser u = CURRENT_USER.get();\nCURRENT_USER.remove(); \u002F\u002F легко забыть!\n\n\u002F\u002F ScopedValue — решение:\nprivate static final ScopedValue\u003CUser> CURRENT_USER = ScopedValue.newInstance();\n\nScopedValue.where(CURRENT_USER, authenticatedUser)\n    .run(() -> {\n        \u002F\u002F CURRENT_USER доступен во всём этом scope\n        processRequest();\n    });\n\n\u002F\u002F В вызываемом коде:\nvoid processRequest() {\n    User user = CURRENT_USER.get(); \u002F\u002F доступно\n    \u002F\u002F user автоматически недоступен после выхода из run()\n}\n```\n\n### Частые ошибки\n\n- Вызвать `get()` вне `run()` — `NoSuchElementException`; ScopedValue доступен только в scope\n- Использовать ThreadLocal с миллионами Virtual Threads — OOM; мигрируйте на ScopedValue\n- ScopedValue для мутабельного состояния — ScopedValue immutable; для мутабельного состояния нужен другой подход\n\n### Как используется в 2026\n\n- ScopedValue финализирован в Java 25\n- Используется для propagation authentication context, trace ID, request metadata\n- Spring Security и Micrometer начинают поддержку ScopedValue для Virtual Threads\n\n> **На собеседовании:** объясните три проблемы ThreadLocal с Virtual Threads (мутабельность, утечки, память) и как ScopedValue решает каждую. Частая ошибка — не знать про автоматическое наследование в child-scope при Structured Concurrency.","","middle",[15],"java-modern",[],null,{"title":19,"description":20,"ogTitle":19,"ogDescription":21,"keywords":22,"schemaAnswer":23,"featuredSnippetReady":24},"Scoped Values — замена ThreadLocal? — Gymterview","Scoped Values — механизм для передачи иммутабельных данных через стек вызовов без явной передачи параметров. Альтернатива `ThreadLocal`, разработанная специальн","Scoped Values — механизм для передачи иммутабельных данных через стек вызовов без явной передачи параметров. Альтернатив",[15,13],"Scoped Values — механизм для передачи иммутабельных данных через стек вызовов без явной передачи параметров. Альтернатива `ThreadLocal`, разработанная специально для Virtual Threads — не создаёт копию на каждый поток и автоматически ограничивает время жизни.",true]