我正在尝试编写一个解决方案,其中单个线程生成可以并行执行的I/O密集型任务.每个任务都有重要的内存数据.所以我希望能够限制暂时待处理的任务数量.
如果我像这样创建ThreadPoolExecutor:
ThreadPoolExecutor executor = new ThreadPoolExecutor(numWorkerThreads, numWorkerThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(maxQueue));
Run Code Online (Sandbox Code Playgroud)
然后在队列填满并且所有线程都已忙时executor.submit(callable)抛出RejectedExecutionException.
executor.submit(callable)当队列已满且所有线程都忙时,我该怎么做才能阻塞?
编辑:我试过这个:
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
Run Code Online (Sandbox Code Playgroud)
它有点实现了我想要实现的效果但是以一种不雅的方式(基本上被拒绝的线程在调用线程中运行,因此这阻止了调用线程提交更多).
编辑:(提问后5年)
对于阅读此问题及其答案的任何人,请不要将接受的答案作为一个正确的解决方案.请仔细阅读所有答案和评论.
为什么,为什么不java.util.concurrent提供其ExecutorServices 的队列长度指标?最近我发现自己做了这样的事情:
ExecutorService queue = Executors.newSingleThreadExecutor();
AtomicInteger queueLength = new AtomicInteger();
...
public void addTaskToQueue(Runnable runnable) {
if (queueLength.get() < MAX_QUEUE_LENGTH) {
queueLength.incrementAndGet(); // Increment queue when submitting task.
queue.submit(new Runnable() {
public void run() {
runnable.run();
queueLength.decrementAndGet(); // Decrement queue when task done.
}
});
} else {
// Trigger error: too long queue
}
}
Run Code Online (Sandbox Code Playgroud)
哪个工作正常,但......我认为这应该作为一部分实现ExecutorService.这是一个愚蠢的错误,容易携带一个与实际队列分开的计数器,计数器应该指示它的长度(让我想起C数组).但是,ExecutorServices是通过静态工厂方法获得的,因此无法简单地扩展优秀的单线程执行器并添加队列计数器.所以我该怎么做: