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

将ThreadLocal传播到从ExecutorService提取的新线程

焦正德
2023-03-14
问题内容

我正在使用ExecutorService和Future(在此处为示例代码)在具有超时的单独线程中运行进程(线程“生成”发生在AOP Aspect中)。

现在,主线程是一个Resteasy请求。Resteasy使用一个或多个ThreadLocal变量来存储一些上下文信息,这些信息需要在Rest方法调用中的某个时刻检索。问题是,由于Resteasy线程在新线程中运行,因此ThreadLocal变量丢失。

将Resteasy使用的任何ThreadLocal变量“传播”到新线程的最佳方法是什么?似乎Resteasy使用了多个ThreadLocal变量来跟踪上下文信息,我想“盲目”将所有信息转移到新线程中。

我已经研究了子类化,ThreadPoolExecutor并使用beforeExecute方法将当前线程传递给池,但是我找不到将ThreadLocal变量传递给池的方法。

有什么建议吗?

谢谢


问题答案:

ThreadLocal与线程关联的实例集保存在每个html" target="_blank">实例的私有成员中Thread。列举这些的唯一机会就是对问题进行一些思考Thread;这样,您可以覆盖线程字段上的访问限制。

一旦获得的集合ThreadLocal,就可以使用beforeExecute()和的afterExecute()钩子在后台线程中进行复制ThreadPoolExecutor,或者通过Runnable为任务创建一个包装器来拦截run()调用以设置一个未设置的必要ThreadLocal实例。实际上,后一种技术可能会更好,因为它会为您提供一个方便的位置,以便ThreadLocal在排队任务时存储值。

更新: 这是第二种方法的更具体的说明。与我的原始描述相反,包装器中存储的全部是调用线程,在执行任务时会对其进行查询。

static Runnable wrap(Runnable task)
{
  Thread caller = Thread.currentThread();
  return () -> {
    Iterable<ThreadLocal<?>> vars = copy(caller);
    try {
      task.run();
    }
    finally {
      for (ThreadLocal<?> var : vars)
        var.remove();
    }
  };
}

/**
 * For each {@code ThreadLocal} in the specified thread, copy the thread's 
 * value to the current thread.  
 * 
 * @param caller the calling thread
 * @return all of the {@code ThreadLocal} instances that are set on current thread
 */
private static Collection<ThreadLocal<?>> copy(Thread caller)
{
  /* Use a nasty bunch of reflection to do this. */
  throw new UnsupportedOperationException();
}


 类似资料:
  • 我有一个包含数千行的数据文件。我正在读取它们并将它们保存在数据库中。我想以50行的批次多线程处理这个过程。当我在文件中读取时,10行被提交给ExecutorService。 我可以在一段时间内循环执行以下操作,直到行结束。。。。 但是,如果处理10行需要时间,我不想将整个文件读入内存。我只想在其中一个线程返回之前提交5个线程,然后提交下一个线程。 假设一个线程需要20秒来保存10条记录,我不希望被

  • 我已经解决了很多与树相关的问题,但是,我仍然对树的一个特定方面(通常是递归)没有信心: 如何将值从叶传播到根? 例如,假设我们有一个二叉树,其中我们必须找到具有最小和的根到叶路径。对于此处的树图像,总和将为7(对应于两条路径0-3-2-1-1或0-6-1)。 我编写了以下代码: 我知道最后一次返回的货币不正确,但是我应该返回什么?从技术上讲,我只想在到达叶节点时返回minVal的值(在中间节点时没

  • 由于对公共EJB方法的Async调用,我有一个继承线程本地变量,我想将其传递给由EJB容器的线程池分配的另一个子线程。发起异步调用的父调用方是REST资源,它是无状态EJB。仅当子线程创建为新线程时,才将值传递给其子线程。一旦在池中创建了线程,它就不会破坏线程,直到服务器被反弹。 考虑到上述事实,我的案例的子线程来自EJB容器维护的线程池。仅当服务器启动后第一次调用资源时,或者如果刚刚在Threa

  • 我们正在开发一个打印服务器,允许用户上传一个文档并通过惠普ePrint打印出来。它需要支持页面提取。 有没有办法从一个单据到另一个单据中提取页面(不丢失格式--例如DOC中的表格),这样大小可以近似于大小?

  • 我正在尝试设置多线程应用程序的跟踪。我已设置线程池: 所以有几个线程。其中一个线程正在侦听SQS队列: 在此代码段中

  • 我在编写一个应用程序时遇到了一些问题。它的工作是用线来解决迷宫。一个线程开始,对于每个分支,它调用另一个类中的静态方法,传递另一个线程需要的参数,然后为每个路径启动线程。我的输出都搞乱了,我不确定这是多线程问题还是引用的问题。下面是一些代码(每个线程都有一个类的新实例): 和返回ValidPaths的方法 CheckEnvirondings使用传递给子级的深度副本(通过构造函数)来验证子级可以采用