是否有ExecutorService
实现,其行为类似于具有以下特征的线程池?
非常标准的线程池行为。您认为ThreadPoolExecutor
会处理此问题,但
executorService = new ThreadPoolExecutor(
2, 10, // min/max threads
60, TimeUnit.SECONDS, // time of inactivity before scaling back
new SynchronousQueue<Runnable>()); // task queue
如果提交的任务超过10个,将抛出异常。切换到LinkedBlockingQueue
将永远不会扩展到两个最小线程之外,除非您将大小限制为new LinkedBlockingQueue<Runnable>(20)
,在这种情况下,将有两个线程处理1-20个任务,2-10个线程处理21 -30个任务,超过30个任务的例外。不漂亮。同时,固定的线程池永远不会缩小非活动线程。
所以,为了得到我所追求的东西,我可以使用不同类型的BlockingQueue
或摆弄一些我错过的其他设置吗?是否有另一个ExceutorService
实现更适合(哪个?),或者我最好通过覆盖execute()
的{{1}}方法自行滚动?
答案 0 :(得分:6)
不幸的是,答案是否定的。关于jre中最好的事情就是有效地没有螺纹地板,只有天花板。这可以通过allowing core threads to timeout完成。
ThreadPoolExecutor tpe = new ThreadPoolExecutor(10, 10, 60, TimeUnit.Seconds, new LinkedBlockingQueue<Runnable>());
tpe.allowCoreThreadTimeOut(true);
由于核心大小为10,因此在提交任务直到10个线程处于活动状态时将启动新线程。之后,任务将在LinkedBlockingQueue中排队。如果一个线程已经处于非活动状态60秒,它将终止。
通过编写实现BlockingQueue和RejectedExecutionHandler的类,可以实现所需的行为,该类检查ThreadPoolExecutors当前状态,然后确定是否应将任务添加到队列中或拒绝该任务。
答案 1 :(得分:0)
这应该可以解决问题:
ThreadPoolExecutor tpe = new ThreadPoolExecutor(1, maxPoolSize, 60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
tpe.setRejectedExecutionHandler((
Runnable r,
ThreadPoolExecutor executor) -> {
// this will block if the queue is full but not until the sun will rise in the west!
try {
if(!executor.getQueue().offer(r, 15, TimeUnit.MINUTES)){
throw new RejectedExecutionException("Will not wait infinitely for offer runnable to ThreadPoolExecutor");
}
} catch (InterruptedException e) {
throw new RejectedExecutionException("Unable to put runnable to queue", e);
}
});