调度执行并行服务多个线程

我有兴趣使用 来生成任务的多个线程 如果之前的任务还没有完成。例如,我需要每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.scheduleWithFixedDelayScheduledExecutorService

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


答案 1

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

final ScheduledExecutorService service = Executors.newScheduledThreadPool(POOL_SIZE);

final Runnable command = new SlowRunnable();

service.scheduleAtFixedRate(
    new Runnable() {
      @Override
      public void run() {
        service.execute(command);
      }
    }, 0, 1, TimeUnit.SECONDS);

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

请注意,虽然我喜欢这个解决方案,因为它最大限度地减少了代码并重用了相同的SchpectedExecutorService,但它的大小必须正确,并且可能无法在每个上下文中使用:如果SlowRunnable非常慢,以至于最多POOL_SIZE个作业一起执行,那么将没有线程来及时运行计划的任务。

此外,如果将间隔设置为 1 TimeUnit.NANOSECONDS,则主 runnable 的执行速度可能会太慢。


答案 2

其中一个 scheduleAtFixedRate 方法是你要找的。它以给定的时间间隔从池中启动线程中的任务,即使以前的任务尚未完成也是如此。如果线程不足以进行处理,请调整池大小约束,如 ThreadPoolExecutor 文档中所述。