我正在一个单独的线程中运行一个带有超时的进程,使用 ExecutorService 和 Future (示例代码here https://stackoverflow.com/questions/1164301/how-do-i-call-some-blocking-method-with-a-timeout-in-java/1164333#1164333)(线程“生成”发生在 AOP 方面)。
现在,主线程是Resteasy http://www.jboss.org/resteasy要求。 Resteasy 使用一个或多个 ThreadLocal 变量来存储我需要在 Rest 方法调用中的某个时刻检索的一些上下文信息。问题是,由于 Resteasy 线程在新线程中运行,因此 ThreadLocal 变量会丢失。
将 Resteasy 使用的任何 ThreadLocal 变量“传播”到新线程的最佳方法是什么?看来 Resteasy 使用多个 ThreadLocal 变量来跟踪上下文信息,我想“盲目地”将所有信息传输到新线程。
我看过子类化ThreadPoolExecutor
并使用执行前 http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#beforeExecute%28java.lang.Thread,%20java.lang.Runnable%29方法将当前线程传递到池中,但我找不到将 ThreadLocal 变量传递到池的方法。
有什么建议吗?
Thanks
的集合ThreadLocal
与线程关联的实例保存在每个线程的私有成员中Thread
。你列举这些的唯一机会就是对Thread
;这样,您可以覆盖线程字段的访问限制。
一旦你可以获得一组ThreadLocal
,您可以使用复制后台线程beforeExecute()
and afterExecute()
的钩子ThreadPoolExecutor
,或者通过创建一个Runnable
拦截任务的包装器run()
调用以设置和取消设置必要的ThreadLocal
实例。实际上,后一种技术可能效果更好,因为它可以为您提供一个方便的地方来存储ThreadLocal
任务排队时的值。
Update:这是第二种方法的更具体的说明。与我最初的描述相反,包装器中存储的所有内容都是调用线程,在执行任务时会询问该线程。
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();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)