问题描述
import java.util.concurrent.Executors
import scala.concurrent.{ExecutionContext, Future}
object TestInheritableThreadLocal {
def main(args: Array[String]): Unit = {
implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(2))
val tl: InheritableThreadLocal[String] = new InheritableThreadLocal[String]()
tl.set("InitialValue")
Future {
println("111 " + Thread.currentThread() + tl.get())
Future {
println("222 " + Thread.currentThread() + tl.get())
}
}
Thread.sleep(3000)
Future {
tl.set("NewInitialValue")
println("333 " + Thread.currentThread() + tl.get())
Future {
println("444 " + Thread.currentThread() + tl.get())
}
Thread.sleep(3000)
}
}
}
输出
111 Thread[pool-1-thread-1,5,main]InitialValue
222 Thread[pool-1-thread-2,5,main]InitialValue
333 Thread[pool-1-thread-1,5,main]NewInitialValue
444 Thread[pool-1-thread-2,5,main]InitialValue
我期待输出的最后一行中出现NewInitialValue,因为333 Thread生成了Thread 444,而tl是一个可继承的本地线程。
I was expecting "NewInitialValue" in the last line of output since 333 Thread spawned of Thread 444 and tl is a Inheritable thread local.
导致此问题的原因是什么以及如何解决?
What is causing this issue and how can it be resolved ?
推荐答案
你不应该依赖。 javadoc声明:
You shouldn't rely on InheritableThreadLocal
when you don't have control over the creation of threads. The javadoc states:
在您的示例中,线程由<$创建c $ c> ExecutorService 由
In your example, threads are being created by the ExecutorService
returned by Executors.newFixedThreadPool(2)
这是执行者将使用最多两个线程来执行您的任务。来自javadoc
That's an executor that will use up to two threads to execute your tasks. From the javadoc
这是一个实现细节,但这些线程是根据需要延迟创建的。当您提交第一个任务 111
时,对 submit
的调用将创建并启动一个新线程。这个新线程将继承值 InitialValue
。类似地,当此线程提交第二个任务 222
时,其对 submit
的调用将强制创建第二个线程它还将继承 InitialValue
。
This is an implementation detail, but those threads are created lazily, as needed. When you submit the first task, 111
, the call to submit
will create and start a new thread. This new thread will inherit the value InitialValue
. Similarly, when this thread submits the second task, 222
, its call to submit
will force the creation of the second thread which will also inherit the InitialValue
.
然后你提交第三个任务, 333
,覆盖 InheritableThreadLocal
的值并打印出来。当您提交第四个任务 444
时, ExecutorService
使用现有线程来执行它。该线程已经有一个值,在之前继承。
Then you submit the third task, 333
, overwrite the InheritableThreadLocal
's value and print it. When you submit the fourth task 444
, the ExecutorService
uses existing threads to execute it. That thread already has a value, inherited earlier.
如果不知道自己想做什么,这很难回答。但是,如果你想有效地使用 InheritableThreadLocal
,那么这一切都归结为知道和控制线程的创建,因此也就是继承链。
That's hard to answer without knowing what you want to do. But, if you want to effectively use InheritableThreadLocal
, it all comes down to knowing and controlling the creation of threads, and therefore the inheritance chain.
您可以创建并使用 ExecutorService
,例如,为每个提交的任务创建并使用新线程。
You could create and use an ExecutorService
that creates and uses a new thread for each submitted task, for example.
同样,您可以使用另一种机制来传播该值: AtomicReference
或不可变值的lambda捕获。
Similarly, you could use another mechanism to propagate that value: an AtomicReference
or lambda capture of an immutable value.
这篇关于ExecutorService线程不继承InheritableThreadLocal值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!