I am a new to the latest Java versions and I found this concept of virtual threads which many servers are now using.
In the same context I wanted to use a ThreadLocal field in the virtual thread concept. Not sure how to implement it.
I am a new to the latest Java versions and I found this concept of virtual threads which many servers are now using.
In the same context I wanted to use a ThreadLocal field in the virtual thread concept. Not sure how to implement it.
In general, the successor API for ThreadLocal
for virtual threads is not yet released. You're looking for ScopedValue
, which is still in preview. See JEP 481: Scoped Values for Java 23.
With that said, ThreadLocal
will still work with virtual threads. Almost all its use cases are better served by other approaches, however.
ThreadLocal
not work well with virtual threads? I see no fault described in the JEP. To quote: “Virtual threads support thread-local variables (ThreadLocal) and inheritable thread-local variables (InheritableThreadLocal), just like platform threads, so they can run existing code that uses thread locals.” The only caveat there is a caution about quantity. –
Goldfinch ThreadLocal
works exactly the same in virtual threads as they do in platform threads. Implying otherwise will prompt unfounded rumors and misunderstanding amongst developers. –
Goldfinch ThreadLocal
. After all, ThreadLocal
is nothing more than a Map
from Thread
to Object
. Interesting to learn, is it possible to "intercept" the reference to carrier's Map
and substitute virtual thread's own Map
? –
Chimene ThreadLocal
with ScopedValue
, do you really think it is possible for frameworks like Spring Security? I have entire answer that doubts it is conceptually possible; might miss something, though. –
Chimene spring.threads.virtual.enabled
. –
Chimene Yes, indeed ScopedValue
is a recommended replacement for ThreadLocal
. JavaDoc for ScopedValue
says:
A ScopedValue should be preferred over a ThreadLocal for cases where the goal is "one-way transmission" of data without using method parameters.
Oracle doc for Virtual thread, section Don't Cache Expensive Reusable Objects in Thread-Local Variables goes along the similar lines.
This is understandable. When virtual thread dismounts from one carrier thread and mounts on another, the thread context must be transferred and ThreadLocal
is evidently a part of this context.
But that's a theory. The reality is different and might depend on the stack you use. The problem with ScopedValue
actually lies ... in its advertised advantage. The same JavaDoc, mentioned above, reads:
A ThreadLocal has an unbounded lifetime and thus continues to have a value after a method completes, unless explicitly removed.
The truth is that very often it is exactly what a framework or library needs: not that much of "unbounded lifetime", but rather a possibility to jump into a thread context at any point of execution/stack and plant there some status. As a result, ThreadLocal
s are used by innumerable amount of frameworks or libraries: Spring Security, Spring Web, MDC, Spring Data JPA, Micrometer, Spring Transaction Management - the list goes on. The usage of ThreadLocal
s is so ubiquitous that it is difficult to name a system which do not use ThreadLocal
.
So, unbeknownst to you, your system might use bunch of ThreadLocal
s.
In some cases it might be marginally possible to replace ThreadLocal
with ScopedValue
: Spring Security Virtual Threads and ThreadLocal thread discusses such attempt in respect of Spring Security, and Logback: availability of MDCs in forks created inside a StructuredTaskScope thread - in respect of MDC, but it is easy to see how awkward and flawed such design might be and the main reason is that ScopedValue
has to be bound to a thread conceptually at the time of its spawning.
Granted, it is one of main goals of Structured Concurrency, but it also means that ScopedValue
is not a drop-in replacement for ThreadLocal
, at least for now.
How the situation might change in near future? Will frameworks and libraries authors jump into Structured Concurrency? I'd rather take the advise Don't Cache Expensive Reusable Objects in Thread-Local Variables lightly and won't attempt to use Structured Concurrency in the cases it does not fit to.
ScopedValue.get()
method I would expect to have at least something like ScopedValue.getLast()
and List<T> ScopedValue.getChain()
–
Polarimeter ScopedValue
is then different from any other value holder, like Integer
and other wrappers or Atomic*
? The idea of ScopedValue
, is, as far as I can see, not to have history of changes, but to have it operating inside of StructuredTaskScope
. Which is more secure than, for example, to have ThreadLocal
being set and reset in servlet Filter
. –
Chimene ScopedValue
turns last into ThreadLocal
from "security" perspective. –
Polarimeter ScopedValue
you deny any value of it in the light of Structured Concurrency? –
Chimene ScopedValue
?). JEP 481
do propose a poor API, that is embarrassing. –
Polarimeter ScopedValue
for the systems, which heavily rely on ThreadLocal
s. If you look at the virtual thread/project Loom-related questions, good half of them are Spring-, Spring Boot-, Tomcat-, MDC-, Micrometer-related, and even if a question is purely generic or theoretical, there is a good chance the OP of such question still uses some of those. And those systems have a tremendous problem with migration from ThreadLocal
to ScopedValue
. –
Chimene ThreadLocal
without interesting in keeping information about previous values. Basically, logging capabilities do require such feature - we need to log a chain of security subjects, a chain of business operations etc. Yes, API is not able to prevent developer from doing stupid things, however, at current moment it enforces developer to do that. –
Polarimeter ThreadLocal
of a thread that handles a request, and when the handling of the request completes the Filter removes this object from this ThreadLocal
. Why this Spring Security Filter would be interested in this thread's ThreadLocal
's history? –
Chimene Subject A
hits REST API, which in turn hits internal privileged method which impersonalizes Subject A
and current security subject becomes Subject SYS
, after that, inside logging framework, I need to log/audit both Subject SYS
and Subject A
, since the last one have initiated the changes. Then, my internal privileged method wants to send data somewhere outside and obviously it needs to use Subject A
(i.e. the first security subject in chain). Please check how @Secured("RUN_AS_...")
works in spring. –
Polarimeter ScopedValue
being “mutable” (despite it’s immutable but just can’t prevent the referenced object from being mutable, as no class in Java can). You want a context object knowing its history? It’s as easy as record Whatever(Whatever previous, OtherType currentValue) {}
Store that in a ScopedValue
and you’re done. Besides that, apparently the current frameworks learned to live with ThreadLocal
not having a history, so why should it suddenly be a problem with ScopeValue
? –
Wyler ThreadLocal
has no history and ScopeLocal
has no history. Nothing has changed in this regard in the last twenty years. This was the status quo even before those frameworks were created. And no, a feature is not broken just because one guy on the internet says so. –
Wyler ScopeLocal
is not going to improve anything, oh no...: someone won't need to write try/finally anymore - best twenty years improvement ever. –
Polarimeter ThreadLocal
and ScopedValue
are about binding a value to a thread only. If you want, for example, advanced push/pop discipline, you could easily build it a top of primitive, but basic set
/get
. Current ThreadLocal
and ScopedValue
design just follows separation of concepts principle. –
Chimene var
is another example, but many think opposite. Virtual threads is an obvious improvement, but if you look how its implementation breaks OOP principles... –
Chimene © 2022 - 2024 — McMap. All rights reserved.
ThreadLocal
in new code. ThreadLocal is useful when you're porting old, single-threaded code that usesstatic
variables into a multi-threaded environment. If you're not declaring static variables, then there's probably no reason to use ThreadLocal, and you should not be declaring static variables in new code. Static and ThreadLocal can make your code significantly more difficult to maintain and significantly more difficult to test. – WincerScopedValue
avoids most of the problems withThreadLocal
. – Hawes