14

ScheduledExecutorService如果之前的任务尚未完成,我有兴趣使用为任务生成多个线程。例如,我需要每 0.5 秒处理一次文件。第一个任务开始处理文件,如果第一个线程未完成,则在 0.5 秒后生成第二个线程并开始处理第二个文件,依此类推。这可以通过以下方式完成:

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

现在我的问题是:为什么我不能这样做executor.scheduleAtFixedRate

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

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

4

2 回答 2

11

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

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(),这可能需要比单个间隔的持续时间更长的时间。

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

此外,如果您将时间间隔设置为 1 TimeUnit.NANOSECONDS,那么主可运行文件的执行也可能会变得太慢。

于 2016-09-06T13:07:51.240 回答
0

您正在寻找的scheduleAtFixedRate方法之一。它以给定的时间间隔从池中的线程中启动一个任务,即使以前的任务还没有完成。如果您用完了线程来进行处理,请按照ThreadPoolExecutor 文档中的详细说明调整池大小限制。

于 2011-07-27T19:43:27.960 回答