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
自333线程产生于444线程以来,我一直期待输出的最后一行出现“ NewInitialValue”,而tl是本地可继承线程。
是什么导致此问题,如何解决?
InheritableThreadLocal
当您无法控制线程的创建时,您不应依赖。Javadoc指出:
[…]创建子线程时,子级将接收父级具有值的所有可继承线程局部变量的初始值。
在您的示例中,线程是由ExecutorService
返回者创建的Executors.newFixedThreadPool(2)
那是一个执行程序,最多将使用两个线程来执行您的任务。从javadoc
创建一个线程池,该线程池重用在共享的无边界队列上操作的固定数量的线程。在任何时候,最多
nThreads
线程都是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,则它们将在队列中等待,直到某个线程可用为止。
这是一个实现细节,但是这些线程是根据需要延迟创建的。当您提交第一个任务时111
,对的调用submit
将创建并启动一个新线程。这个新线程将继承该值InitialValue
。同样,当该线程提交第二个任务时222
,其对的调用submit
将强制创建第二个线程,该第二个线程也将继承InitialValue
。
然后,您提交第三个任务,333
覆盖InheritableThreadLocal
的值并打印。当您提交第四个任务时444
,会ExecutorService
使用现有线程来执行它。该线程已经具有一个值,该值是先前继承的。
怎么解决
如果不知道自己想做什么,很难回答。但是,如果您想有效地使用InheritableThreadLocal
,那么一切都取决于了解和控制线程的创建,并因此控制继承链。
例如,您可以创建并使用ExecutorService
,为每个提交的任务创建并使用新线程。
同样,您可以使用另一种机制来传播该值:AtomicReference
不变值的lambda捕获。
是什么导致了这个问题,如何解决?
我正在尝试执行以下代码: 上述类由测试类继承: 以下是testng.xml文件: 我正在通过运行testng.xml文件并行执行上述测试方法。根据我的理解,可继承线程局部变量的值可以被子线程访问。但是当我执行上述测试类时,我观察到在测试方法中,可继承线程局部变量的值为。根据我的理解,“BeforeMethod”和“test方法”是BeforeClass方法的子线程。 以下是输出: 那么,为什么可继
本文向大家介绍java多线程编程之InheritableThreadLocal,包括了java多线程编程之InheritableThreadLocal的使用技巧和注意事项,需要的朋友参考一下 InheritableThreadLocal的作用: 当我们需要在子线程中使用父线程中的值得时候我们就可以像使用ThreadLocal那样来使用InheritableThreadLocal了。 首先我们来看一
假设我有一个Executors静态工厂方法的ExecutorService实例。 如果我从某个线程提交了一个调用,其中RetVal不是线程安全的本地实例化对象,那么当我从同一个线程获得()它时,我需要担心retvals的完整性吗?人们说局部变量是线程安全的,但我不确定当您返回一个本地实例化的对象并从其他线程接收它时,它是否适用。 下面是我的定制实现,我只是为了测试。您可以忽略EType枚举。
我从主线程调用了下面的代码,使用ExecutorService池并启动一个线程来处理找到的每个文件。我正在尝试了解当主线程被kill命令终止时ExecutorService的行为。生成的线程会发生什么?一旦完成工作,它们会立即被杀还是终止? 还有没有更好/更安全的方法来编写下面的代码段,特别是如果我在无限循环中运行这部分,例如等待文件被放到输入目录并分配线程来处理它们?在这种情况下,我应该创建一个
FAQs in section [24]: [24.1] 如何表示“私有继承”? [24.2] 私有继承和组合(composition)有什么类似? [24.3] 我应该选谁:组合还是私有继承? [24.4] 从私有继承类到父类需要指针类型转换吗? [24.5] 保护继承和私有继承的关系是什么? [24.6] 私有继承和保护继承的访问规则是什么? 24.1 如何表示“私有继承”? 用 : priv