使用Executors.newFixedThreadPool(int nThreads)
是最小化创建太多线程的开销的好方法,但是如果所有线程都在等待另一个作业,而该作业本身正在等待池中的空闲线程,则可能导致死锁。有时这个问题可以通过使用多个线程池来解决,但有时却不能。我正在寻找行为类似于newFixedThreadPool
的东西,除了所有池线程都被阻塞的情况下——在这种情况下,池应该增长,尽管它的预定义边界。有这样的东西吗?
实际上,死锁在这里并不是那么重要。真正的问题是"如何管理运行的线程的数量",而不是它们的总数。当试图在不创建不必要的许多线程的情况下充分利用CPU时,这也是很有趣的。
如果您有争用问题,这是一个设计问题。如果你想像你描述的那样快速解决问题,你只会治愈症状,而不是潜在的疾病。
您应该使用其他方法重构您的设计以消除死锁。
让线程池中的线程阻塞等待同一线程池中的其他线程通常不是一个好主意。
我会尝试将设计更改为非阻塞设计。如果一个线程需要同一执行器正在处理的另一个操作的结果,我会让它将一个任务提交回执行器,以便在第二个操作完成后运行。或者将对象放入队列中,以便在其他作业完成后提取。
或者,您可以像Swing对模态对话框所做的那样,让即将阻塞的线程启动子线程来继续处理请求,直到父线程解除阻塞。这是很棘手的,但需要你手动管理线程,这比使用Executor安全得多。
Executor.newCachedThreadPool();
缓存的线程池将检查是否有可用的线程。如果存在,线程池将重用该线程。如果不是,线程池将创建一个新线程。线程的生存时间为60秒,因此在60秒后,额外的线程将被终止。