ScheduledExecutorService类的方法“scheduleAtFixedRate”如何工作?

时间:2016-10-03 11:16:02

标签: java multithreading concurrency

我正在尝试使用类scheduleAtFixedRate的方法ScheduledExecutorService的示例。代码是:

ScheduledExecutorService service = Executors.newScheduledThreadPool(4);
        IntStream.range(0, 4).forEach(i -> service.scheduleAtFixedRate(() -> {try {
            System.out.println(i + " task completed!");
        } catch (Exception e) {
            e.printStackTrace();
        }}, 
                0, 3, TimeUnit.SECONDS));
        service.shutdown();

输出结果为:

1 task completed!
2 task completed!
0 task completed!

为什么不执行所有4个任务?

如果省略service.shutdown();,则所有任务也会被执行并重复执行,但会导致内存泄漏。根据文档,任何在关闭之前都应该执行注册任务。

此外,如果我使用Thread暂停当前Thread.sleep()一段时间,则输出包含以下所有任务:

ScheduledExecutorService service = Executors.newScheduledThreadPool(4);
        IntStream.range(0, 4).forEach(i -> service.scheduleAtFixedRate(() -> {try {
            System.out.println(i + " task completed!");
        } catch (Exception e) {
            e.printStackTrace();
        }}, 
                0, 3, TimeUnit.SECONDS));

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        service.shutdown();

输出:

0 task completed!
3 task completed!
2 task completed!
1 task completed! 

这是方法scheduleAtFixedRate的预期行为吗?

更新

当我毫不拖延地使用submit代替scheduleAtFixedRate时,行为接近预期。调用shutdown()可以完成所有4个任务,而shutdownNow()仅限3:

ScheduledExecutorService service = Executors.newScheduledThreadPool(4);
        IntStream.range(0, 4).forEach(i -> service.submit(() -> {

        System.out.println(i + " task completed");}));

        service.shutdown();

如果我不使用ScheduledExcecutorService并使用ExecutorService代替:

ExecutorService service = Executors.newFixedThreadPool(4);
    IntStream.range(0, 4).forEach(i -> service.submit(() -> {

    System.out.println(i + " task completed");}));

     service.shutdown();

然后,无论我使用shutdown() shutdownNow()的{​​{1}},所有4个任务都会完成。

ScheduledExecutorService似乎在任务提交方面略有不同,可能在shutdown()shutdownNow()上。

1 个答案:

答案 0 :(得分:-1)

在ExecutorService.class

的文档中找到了这个
  

此方法不会等待以前提交的任务        完成执行。使用{@link #awaitTermination awaitTermination}         这样做。

查看此Link了解详情。 从我的PC我发现有时所有四个线程都完成执行。这取决于调用shudown的时间。如果要等待线程完成,请使用awaitTermination方法。

当您让main线程进入睡眠状态时,执行shutdown需要花费一些时间,直到那时所有任务都结束了。