ThreadPoolExecutor当队列已满时阻塞? [英] ThreadPoolExecutor Block When Queue Is Full?

查看:1924
本文介绍了ThreadPoolExecutor当队列已满时阻塞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用ThreadPoolExecutor执行大量任务。下面是一个假设的例子:

I am trying to execute lots of tasks using a ThreadPoolExecutor. Below is a hypothetical example:

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,因为任务数超过了工作队列的大小。但是,我想要的行为是有主线程块,直到队列中有空间。

The problem is that I quickly get a java.util.concurrent.RejectedExecutionException since the number of tasks exceeds the size of the work queue. However, the desired behavior I am looking for is to have the main thread block until there is room in the queue. What is the best way to accomplish this?

推荐答案

在一些非常狭窄的情况下,你可以实现一个java.util.concurrent。 RejectedExecutionHandler,做你所需要的。

In some very narrow circumstances, you can implement a java.util.concurrent.RejectedExecutionHandler that does what you need.

RejectedExecutionHandler block = new RejectedExecutionHandler() {
  rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
     executor.getQueue().put( r );
  }
};

ThreadPoolExecutor pool = new ...
pool.setRejectedExecutionHandler(block);

现在。这是一个非常糟糕的主意,原因如下:

Now. This is a very bad idea for the following reasons


  • 这很容易死锁,因为池中的所有线程可能会在你放入队列的东西可见之前死亡。通过设置合理的保持活动时间来缓解这种情况。

  • 任务不会像你的执行者那样被包装。许多执行器实现在执行之前将它们的任务封装在某种跟踪对象中。查看您的来源。

  • API强烈建议您不要通过getQueue()添加,有时可能会被禁止。

一个几乎总是更好的策略是安装ThreadPoolExecutor.CallerRunsPolicy,它会通过在调用execute()的线程上运行任务来调节你的应用程序。

A almost-always-better strategy is to install ThreadPoolExecutor.CallerRunsPolicy which will throttle your app by running the task on the thread which is calling execute().

然而,有时一个拥有所有内在风险的封锁策略,实际上是你想要的。

However, sometimes a blocking strategy, with all its inherent risks, is really what you want. I'd say under these conditions


  • 您只有一个线程调用execute()


  • 您绝对需要限制运行此工作的线程数(通常是出于外部原因),而调用者运行策略

  • 您的任务具有不可预测的大小,因此如果池暂时忙于4个短任务并且您的一个线程调用执行陷入了一个大任务,调用者运行可能引入饥饿。

  • You only have one thread calling execute()
  • You have to (or want to) have a very small queue length
  • You absolutely need to limit the number of threads running this work (usually for external reasons), and a caller-runs strategy would break that.
  • Your tasks are of unpredictable size, so caller-runs could introduce starvation if the pool was momentarily busy with 4 short tasks and your one thread calling execute got stuck with a big one.

所以,正如我所说。

祝你好运。

这篇关于ThreadPoolExecutor当队列已满时阻塞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆