我正在尝试编写一个解决方案,其中单个线程产生可以并行执行的 I/O 密集型任务。每个任务都有重要的内存数据。所以我希望能够限制当前待处理的任务数量。
如果我这样创建 ThreadPoolExecutor:
ThreadPoolExecutor executor = new ThreadPoolExecutor(numWorkerThreads, numWorkerThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(maxQueue));
然后 executor.submit(callable)
在队列填满并且所有线程都已经忙时抛出 RejectedExecutionException
。
当队列已满且所有线程都忙时,我该怎么做才能使 executor.submit(callable)
阻塞?
编辑: 我试过this :
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
而且它在某种程度上达到了我想要达到的效果,但是以一种不优雅的方式(基本上被拒绝的线程在调用线程中运行,所以这会阻止调用线程提交更多)。
编辑:(提出问题 5 年后)
对于阅读此问题及其答案的任何人,请不要将已接受的答案视为一种正确的解决方案。请仔细阅读所有答案和评论。
最佳答案
我也做过同样的事情。诀窍是创建一个 BlockingQueue,其中 offer() 方法实际上是 put()。 (你可以使用任何你想要的基本 BlockingQueue 实现)。
public class LimitedQueue<E> extends LinkedBlockingQueue<E>
{
public LimitedQueue(int maxSize)
{
super(maxSize);
}
@Override
public boolean offer(E e)
{
// turn offer() and add() into a blocking calls (unless interrupted)
try {
put(e);
return true;
} catch(InterruptedException ie) {
Thread.currentThread().interrupt();
}
return false;
}
}
请注意,这仅适用于 corePoolSize==maxPoolSize
的线程池,因此请小心(请参阅注释)。
关于Java:ExecutorService 在特定队列大小后阻止提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4521983/