Home > database >  Why the order was not guaranteed by Executors.newSingleThreadExecutor()?
Why the order was not guaranteed by Executors.newSingleThreadExecutor()?

Time:11-26

I am using JDK/Java 19 in Windows 11 x64, IntelliJ IDEA 2022 Ultimate.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ZooInfo {

    public static void main(String[] args) {
        ExecutorService executorService = null;
        Runnable runnable1 = () -> System.out.println("Printing zoo inventory");
        Runnable runnable2 = () -> {
            for (int i = 0; i < 3; i  ) {
                System.out.println("Printing record "   i);
            }
        };
        try {
            executorService = Executors.newSingleThreadExecutor();
            System.out.println("Begin");
            executorService.execute(runnable1);
            executorService.execute(runnable2);
            executorService.execute(runnable1);
            System.out.println("End.");
        } finally {
            if (executorService != null) {
                executorService.shutdown();
            }
        }
    }

}

// Result:

// Begin
// End.
// Printing zoo inventory
// Printing record 0
// Printing record 1
// Printing record 2
// Printing zoo inventory

I read page 850, book OCP Oracle Certified Professional Java SE 11 Developer - Complete Study Guide), they said

With a single-thread executor, results are guaranteed to be executed sequentially.

Why the order was not guaranteed by Executors.newSingleThreadExecutor() ? ("end" not at the end of line in console's result.)

CodePudding user response:

You neglected to wait for the executor service to complete its work.

You ignored all the boilerplate code given to you in the shutdownAndAwaitTermination shown in the Javadoc for ExecutorService.

executorService = Executors.newSingleThreadExecutor();
System.out.println("Begin");
executorService.execute(runnable1);
executorService.execute(runnable2);
executorService.execute(runnable1);
shutdownAndAwaitTermination( executorService ) ;  // Block here to wait for executor service to complete its assigned tasks. 
System.out.println("End.");

Your original thread happened to finish its work earlier than did the thread of the executor service. That is the nature of independent threads: various threads accomplish various amounts of work in various amounts of time.

CodePudding user response:

Your program has two threads:

  1. The main one, from which you invoke executorService.execute and all the rest.
  2. The Executors.newSingleThreadExecutor()'s thread

The runnables you pass to the newSingleThreadExecutor will indeed be run sequentially on that thread, but it doesn't mean everything in your program runs sequentially relative to those runnables. Your main thread will keep going, unless you somehow wait on the main thread for the tasks to complete (for example, by invoking executorService.shutdown() and then awaitTermination(...) to wait for the existing jobs to finish). You could also use submit rather than execute for each runnable; that would give you back a Future, which you can then call get(...) on to wait for it to finish (you would have to do this for each runnable. executorService.invokeAll(...) makes this a bit easier.

CodePudding user response:

Because main method is independent with executorService = Executors.newSingleThreadExecutor();

  •  Tags:  
  • java
  • Related