ScheduledThreadPoolExecutor和corePoolSize 0?

Mar*_* C. 15 java concurrency multithreading threadpool

ScheduledThreadPoolExecutor如果没有工作要做,我想有一个也停止最后一个线程,并且如果有新任务则创建(并保持线程活动一段时间).但是,一旦没有更多的工作要做,它应该再次丢弃所有线程.

我天真地创建了它,new ScheduledThreadPoolExecutor(0)但结果是,没有创建任何线程,也没有执行任何计划任务.

任何人都可以告诉我,如果我能够实现我的目标而不用自己的包装ScheduledThreadpoolExecutor吗?

提前致谢!

小智 14

实际上你可以做到,但它不明显:

  • 创建一个新的ScheduledThreadPoolExecutor
  • 在构造函数中,将核心线程设置为所需的最大线程数
  • 设置执行程序的keepAliveTime
  • 最后,允许核心线程超时

    m_Executor = new ScheduledThreadPoolExecutor ( 16,null );
    m_Executor.setKeepAliveTime ( 5, TimeUnit.SECONDS );
    m_Executor.allowCoreThreadTimeOut ( true );
    
    Run Code Online (Sandbox Code Playgroud)

    这仅适用于Java 6


Isa*_*lst 8

阅读ThreadPoolExecutor javadocs可能表明Alex V的解决方案没问题.但是,这样做会导致不必要地创建和销毁线程,而不像一个兑现的线程池.ScheduledThreadPool不适用于可变数量的线程.看过源代码后,我确信几乎每次提交任务时都会产生一个新线程.即使您只提交延迟任务,Joe的解决方案也应该有效.

PS.我会监视你的线程,以确保你不会在当前的实现中浪费资源.


Joe*_*han 7

我怀疑提供的任何内容java.util.concurrent都不会为您执行此操作,只是因为如果您需要预定的执行服务,那么您通常会执行重复性任务.如果你有一个重复的任务,那么通常更有意义的是保持相同的线程并将其用于下一次重复任务,而不是拆除你的线程并在下一次重复时建立一个新线程.

当然,计划的执行可用于非经常性任务之间插入延迟,或者它可能的情况下在资源如此稀缺和复发是如此罕见,它是有道理的,直到新的工作到达推倒所有线程使用.所以,我可以看到你的提案肯定有意义的案例.

为了实现这一点,我会考虑尝试将缓存的线程池Executors.newCachedThreadPool与单线程的预定执行程序服务(即new ScheduledThreadPoolExecutor(1))一起包装起来.任务可以通过安排执行程序服务可以预定,但预定的任务将被包裹在这样一种方式,而不是你的单线程的安排执行他们执行的单线程执行程序将其移交到实际缓存的线程池执行.

当完全没有工作要做时,这种妥协会让你最多运行一个线程,并且当你需要做很多工作时,它会为你提供所需数量的线程(在你的系统范围内) .

  • 感谢您详细的回答。实际上,我将 ScheduledThreadPool 用于延迟操作,而不是用于重复操作。大多数操作都是一次性操作,我不想每次都创建一个线程,我也不想在需要这样做的各种类之间明确地手动共享 ScheduledExecutorService。 (2认同)

Esk*_*ola 5

此问题是ScheduledThreadPoolExecutor中的已知错误(错误ID 7091003),已在Java 7u4中修复.虽然看了补丁,但修复是"即使corePoolSize为0,也至少启动一个线程".