当前位置: 首页 > 面试题库 >

ExecutorService线程未继承InheritableThreadLocal值

齐元章
2023-03-14
问题内容
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