gpt4 book ai didi

java - 将 InheritableThreadLocal 与 ThreadPoolExecutor 一起使用——或者——不重用线程的 ThreadPoolExecutor

转载 作者:太空狗 更新时间:2023-10-29 22:41:18 26 4
gpt4 key购买 nike

我正在尝试同时使用 InheritableThreadLocalThreadPoolExecutor

这是因为 ThreadPoolExecutor 为每个池重用线程(毕竟它是一个池),这意味着 InheritableThreadLocal 没有按预期工作。现在这个问题对我来说似乎很明显,但追踪起来特别麻烦。

我使用 InheritableThreadLocal 这样几个顶级进程中的每一个都有自己的数据库连接,用于它自己和它产生的任何子进程。我不只是使用一个共享连接池,因为每个顶级进程在提交到数据库和/或准备大量反复使用的 PreparedStatements 之前,都会对其连接进行大量多步骤工作。

我在这些顶级进程之间使用了一个共享的ThreadPoolExecutor,因为有些行为需要被控制。例如即使我可能有 4 个顶级进程在运行,我也只能让任何一个进程一次写入数据库(或者系统需要访问其他一些共享资源)。所以我会让顶层进程创建一个 Runnable 并将其发送到共享的 ThreadPoolExecutor 以确保不超过一个(或两个或三个,视情况而定)可能)在整个系统中同时运行。

问题在于,因为 ThreadPoolExecutor 将其线程重用于池,InheritableThreadLocal 正在获取在该池中运行的原始值,而不是处于将 Runnable 发送到 ThreadPoolExecutor 的顶级进程中。

  • 有什么方法可以强制 ThreadPoolExecutor 中的工作池使用创建 Runnable 的进程上下文中的 InheritableThreadLocal 值比在重用线程池的上下文中?

  • 或者,是否有任何 ThreadPoolExecutor 实现在每次启动新的 Runnable 时创建一个新线程?出于我的目的,我只关心将同时运行的线程数量限制为固定大小。

  • 人们是否有任何其他解决方案或建议可以帮助我实现上述目标?

(虽然我意识到我可以通过将数据库连接从类传递到类到子线程到子线程来解决问题,就像某种社区自行车一样,但我想避免这种情况。)

StackOverflow 上有一个问题,InheritableThreadLocal and thread pools ,这也解决了这个问题。但是,该问题的解决方案似乎是 InheritableThreadLocal 的糟糕用例,我认为这不适用于我的情况。

感谢您的任何想法。

最佳答案

使用 InheritedThreadLocal 几乎肯定是错误的。可能你不会问这个问题,如果你能适应那个奇怪的工具。首先也是最重要的是,它非常容易泄漏,并且值通常会在一些完全奇怪的线程中逃逸。

至于 Runnable 与上下文相关联。重写 ExecutorPool 的 publicvoid execute(Runnable command) 并首先使用带有您想要的值的上下文包装 Runnable InheritedThreadLocal.

包装类应该看起来像

class WrappedRunnable extends Runnable{
static final ThreadLocal<Ctx> context=new ThreadLocal<Ctx>();
final Runnable target;
final Ctx context;
WrappedRunnable(Ctx context, Runnable target){...}

public void run(){
ctx.set(context);
try{
target.run();
}finally{
ctx.set(null);//or ctx.remove()
}
}
}

Alternatively, is there any implementation of ThreadPoolExecutor that creates a new >thread each time it starts a new Runnable? For my purposes I only care about gating the >number of simultaneously running threads to a fixed size.

虽然从性能的角度来看确实很糟糕,但您可以实现自己的,基本上您只需要 execute(Runnable task) 方法用于生成新线程的 Executor 和启动它。

关于java - 将 InheritableThreadLocal 与 ThreadPoolExecutor 一起使用——或者——不重用线程的 ThreadPoolExecutor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9012371/

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