简体   繁体   中英

How does the method “scheduleAtFixedRate” of the class ScheduledExecutorService work?

I am trying an example using the method scheduleAtFixedRate of the class ScheduledExecutorService . The code is:

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();

The output is:

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

Why are not all 4 tasks executed?

If I omit the service.shutdown(); then all the tasks are executed and repeatedly as well, but it leads to memory leak. According to the docs any before shutdown registered task should be executed.

Moreover, if I pause the current Thread for a while using Thread.sleep() , then the output contains all the tasks as:

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();

Output:

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

Is this the expected behavior of the method scheduleAtFixedRate ?

Update:

When I use submit instead of scheduleAtFixedRate without delay then the behavior comes close to the expected. Calling shutdown() allows all 4 tasks to complete while shutdownNow() only 3:

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

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

        service.shutdown();

If I refrain from ScheduledExcecutorService and use ExecutorService instead as:

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

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

     service.shutdown();

then all 4 tasks are always completed whether I use shutdown() of shutdownNow() .

It seems that the ScheduledExecutorService behaves a little bit different on the task submission and perhaps on shutdown() and shutdownNow() .

Found this in the documentation of ExecutorService.class

This method does not wait for previously submitted tasks to complete execution. Use {@link #awaitTermination awaitTermination} to do that.

Check this Link for more info. From my PC I found out that sometimes all four threads complete execution. It depends on the time when shudown is called. Use awaitTermination method if you want to wait for your threads to complete.

When you made your main thread to sleep, it took time to execute shutdown and until then all the tasks were over.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM