我正在尝试使用 ThreadPoolExecutor 执行大量任务。下面是一个假设的例子:
def workQueue = new ArrayBlockingQueue<Runnable>(3, false)
def threadPoolExecutor = new ThreadPoolExecutor(3, 3, 1L, TimeUnit.HOURS, workQueue)
for(int i = 0; i < 100000; i++)
threadPoolExecutor.execute(runnable)
问题是我很快就得到了java.util.concurrent.RejectedExecutionException
因为任务的数量超过了工作队列的大小。然而,我正在寻找的期望行为是让主线程阻塞,直到队列中有空间。实现这一目标的最佳方法是什么?
在某些非常有限的情况下,您可以实现一个 java.util.concurrent.RejectedExecutionHandler 来完成您需要的操作。
RejectedExecutionHandler block = new RejectedExecutionHandler() {
rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
executor.getQueue().put( r );
}
};
ThreadPoolExecutor pool = new ...
pool.setRejectedExecutionHandler(block);
现在。这是一个非常糟糕的主意由于以下原因
- 它很容易出现死锁,因为在您放入队列的内容可见之前,池中的所有线程可能都会死亡。通过设置合理的保持活动时间来缓解这种情况。
- 任务并未按照执行者期望的方式进行包装。许多执行器实现在执行之前将其任务包装在某种跟踪对象中。看看你的来源。
- API 强烈建议不要通过 getQueue() 添加,并且在某些时候可能会被禁止。
一个几乎总是更好的策略是安装 ThreadPoolExecutor.CallerRunsPolicy ,它将通过在调用execute()的线程上运行任务来限制您的应用程序。
然而,有时,具有所有固有风险的阻止策略确实是您想要的。我想说在这些条件下
- 你只有一个线程调用execute()
- 你必须(或想要)有一个非常小的队列长度
- 您绝对需要限制运行此工作的线程数量(通常出于外部原因),而调用者运行策略会打破这一点。
- 您的任务大小不可预测,因此,如果池暂时忙于 4 个短任务,而调用执行的一个线程被一个大任务卡住,则调用者运行可能会导致饥饿。
所以,正如我所说。它很少需要,而且可能很危险,但就这样吧。
祝你好运。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)