gpt4 book ai didi

java - 将 ThreadLocal 传播到从 ExecutorService 获取的新线程

转载 作者:IT老高 更新时间:2023-10-28 21:13:01 24 4
gpt4 key购买 nike

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

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

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

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

有什么建议吗?

谢谢

最佳答案

与线程关联的一组 ThreadLocal 实例保存在每个 Thread 的私有(private)成员中。列举这些的唯一机会是对 Thread 进行一些反射(reflection);这样,您可以覆盖线程字段的访问限制。

一旦你可以得到 ThreadLocal 的集合,你就可以使用 beforeExecute()afterExecute() 钩子(Hook)在后台线程中复制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();
}

关于java - 将 ThreadLocal 传播到从 ExecutorService 获取的新线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7259906/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com