2011-07-27 43 views
6

我有兴趣使用ScheduledExecutorService为任务产生多个线程,前提是任务尚未完成。例如,我需要每0.5秒处理一个文件。第一个任务开始处理文件,在0.5s之后,如果第一个线程没有完成,第二个线程被产生并且开始处理第二个文件,等等。这可以通过像这样做:ScheduledExecutorService多个并行线程

ScheduledExecutorService executor = Executors.newScheduledThreadPool(4) 
    while (!executor.isShutdown()) { 
     executor.execute(task); 
     try { 
      Thread.sleep(500); 
     } catch (InterruptedException e) { 
      // handle 
     } 
    } 

现在我的问题:为什么我不能executor.scheduleAtFixedRate做呢?

我得到的是,如果第一个任务花费更长时间,第二个任务将在第一个完成时立即启动,但即使执行程序具有线程池,也不会启动新线程。 executor.scheduleWithFixedDelay很清楚 - 它执行的任务在它们之间具有相同的时间跨度,并且完成任务需要多长时间无关紧要。所以可能我误解了ScheduledExecutorService的目的。

也许我应该看看另一种执行者?或者只是使用我在这里发布的代码?有什么想法吗?

回答

0

scheduleAtFixedRate方法之一就是你要找的。它以给定的时间间隔从池中的线程中启动任务,即使之前的任务尚未完成。如果您的线程不足以执行处理,请调整池大小约束,详见ThreadPoolExecutor docs

+1

您链接到scheduleAtFixedRate方法和javadoc指出:“如果这个任务的任何执行比其周期需要更长的时间,那么随后的执行中可能起步晚,但不会同时执行。”这就是它的工作原理,当我尝试... scheduleWithFixedDelay也不适合,因为它开始计算第一个任务结束后的延迟。而线程池的大小并不重要。这对我来说很奇怪,ScheduledExecutorService没有并行执行的方法,或者我错过或误解了某些东西,这就是为什么林问:) – nesvarbu

+0

哦,我明白了。我错过了。我想这个问题会是:“如果你想一次执行其中的两个,他们真的是同样的任务吗?”如果你确信它们是,那么我认为java.util.concurrent可能不支持这种特殊用法。 –

5

我已经通过启动一个嵌套的匿名可运行在每个计划执行解决了这个问题:

​​3210

有了这个例子中会有1线程每间隔一个快速指令执行,因此它将肯定是下一个时间间隔到期时结束。剩下的POOL_SIZE-1线程将并行执行SlowRunnable的run(),这可能需要比单个时间间隔的持续时间更长的时间。

请注意,尽管我最喜欢这个解决方案,因为它最小化了代码并重用了相同的ScheduledExecutorService,但它必须正确调整大小,并且可能在每个上下文中都不可用:如果SlowRunnable速度太慢,以至于执行POOL_SIZE作业在一起,将不会有线程及时运行计划任务。

此外,如果将间隔设置为1 TimeUnit.NANOSECONDS,它可能会变得太慢,并且主可运行的执行也会变得太慢。