我希望有一个ScheduledThreadPoolExecutor
,如果没有工作要做,它也会停止最后一个线程,如果有新任务,则创建(并保持线程活动一段时间)。但是,一旦没有更多工作要做,它应该再次丢弃所有线程。
我天真地将其创建为new ScheduledThreadPoolExecutor(0)
,但结果是,没有创建任何线程,也没有执行任何计划任务。
如果没有在ScheduledThreadpoolExecutor
周围编写自己的包装,我能否告诉我是否可以达到目标?
提前致谢!
答案 0 :(得分:14)
实际上你可以做到,但不明显:
最后,允许核心线程超时
m_Executor = new ScheduledThreadPoolExecutor ( 16,null );
m_Executor.setKeepAliveTime ( 5, TimeUnit.SECONDS );
m_Executor.allowCoreThreadTimeOut ( true );
这仅适用于Java 6,但
答案 1 :(得分:8)
阅读ThreadPoolExecutor javadocs可能表明Alex V的解决方案没问题。但是,这样做会导致不必要地创建和销毁线程,而不像一个兑现的线程池。 ScheduledThreadPool不适用于可变数量的线程。看过源代码后,我相信你几乎每次提交任务时都会产生一个新的线程。即使您只提交延迟任务,Joe的解决方案也应该有效。
PS。我会监视你的线程,以确保你不会在当前的实现中浪费资源。
答案 2 :(得分:7)
我怀疑java.util.concurrent
中提供的任何内容都不会为您执行此操作,因为如果您需要预定的执行服务,那么您通常会执行重复性任务。如果你有一个重复的任务,那么通常更有意义的是保持相同的线程并将其用于下一次重复任务,而不是拆除你的线程并且必须构建一个新的一个在下一次复发。
当然,可以使用预定的执行程序在非重复任务之间插入延迟,或者可以在资源非常稀缺的情况下使用它,并且重复发生的频率很低,以至于拆除所有线程直到新的工作到了。所以,我可以看到你的提案肯定有意义的案例。
为了实现这一点,我会考虑尝试将来自Executors.newCachedThreadPool
的缓存线程池与单线程调度执行程序服务(即new ScheduledThreadPoolExecutor(1)
)一起包装。任务可以通过预定的执行程序服务进行调度,但是计划的任务将以这样一种方式包装,即单线程执行程序不会让您的单线程调度执行程序执行它们,而是将它们交给缓存的线程池以实现执行。
当没有任何工作要做的时候,这种妥协会让你最多运行一个线程,并且当你有很多时,它会给你你所需要的线程数(在系统的限制范围内)工作要做。
答案 3 :(得分:5)
此问题是ScheduledThreadPoolExecutor(Bug ID 7091003)中的已知错误,已在Java 7u4中修复。虽然looking at the patch,但修复是“即使corePoolSize为0,也会启动至少一个线程。”