Understand the use of ExecutorService in java multithreading

  • 2020-05-17 05:40:16
  • OfStack

The java.util.concurrent package provides classes for multithreaded operations. The most commonly used are ExecutorService and its implementation classes (e.g. ThreadPoolExecutor), Executor, Executors, Future, Callable, etc

1. ExecutorService(inherited from Executor) interface: provides some asynchronous multithreaded operation methods, such as execute(), submit(), shutdown(), shutdownNow(), etc

2. Executor interface: performs the submitted task (thread) with only 1 method execute(Runnable a)

2. Executors class: provides some factory methods and some public methods to manipulate Executor subclasses and ThreadFactory, such as newXXX(), xxxThreadFactory(), etc

3. Futrue interface: represents the result of thread execution and provides methods to get the result of thread execution and cancel the thread, such as get(), cancle(), etc

4. Callable interface: the thread provided by JDK1.5 with the return value executes the new interface

Make a brief note of your understanding of ExecutorService and Future

Code:


public class Main {
  private static int count = 0;

  public static void main(String[] args){
    List<Future> resultList = new LinkedList<>();

    /**
     * Executors.newCachedThreadPool()  create 1 Thread cache pool, if 60s If the thread is not used, the thread is stopped and removed from the cache pool 
     * Executors.newScheduledThreadPool()  create 1 A fixed thread pool in which threads are scheduled to execute at a set time 
     * Executors.newFixedThreadPool()   Has a fixed thread cache pool 
     * Executors.newSingleThreadExecutor()  Capacity of 1 The thread cache pool will only be available 1 A thread 
     */
    ExecutorService executorService = Executors.newCachedThreadPool();
    for(int i=0; i<10; i++){
      Future future = executorService.submit(new Callable<String>() {
        @Override
        public String call() {
          try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          int count = Main.count;
          System.out.println(Thread.currentThread().getName() + "..start Main count:..." + count);
          Main.count = ++count;
          System.out.println(Thread.currentThread().getName() + "..end Main count:..." + Main.count);
          return Thread.currentThread().getName();
        }
      });
      resultList.add(future);
    }
    executorService.shutdown();
    for(Future future: resultList){
      try {
        System.out.println(future.get() + "..is over...");
      } catch (InterruptedException e) {
        e.printStackTrace();
      } catch (ExecutionException e) {
        e.printStackTrace();
      }
    }
    System.out.println("main thread end...");
  }
}

Output:


pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
pool-1-thread-6
pool-1-thread-7
pool-1-thread-8
pool-1-thread-9
pool-1-thread-10
pool-1-thread-1..start Main count:...0
pool-1-thread-2..start Main count:...0
pool-1-thread-3..start Main count:...1
pool-1-thread-2..end Main count:...1
pool-1-thread-1..end Main count:...1
pool-1-thread-3..end Main count:...2
pool-1-thread-1..is over...
pool-1-thread-2..is over...
pool-1-thread-4..start Main count:...2
pool-1-thread-3..is over...
pool-1-thread-4..end Main count:...3
pool-1-thread-4..is over...
pool-1-thread-5..start Main count:...3
pool-1-thread-5..end Main count:...4
pool-1-thread-5..is over...
pool-1-thread-6..start Main count:...4
pool-1-thread-6..end Main count:...5
pool-1-thread-6..is over...
pool-1-thread-7..start Main count:...5
pool-1-thread-7..end Main count:...6
pool-1-thread-7..is over...
pool-1-thread-8..start Main count:...6
pool-1-thread-8..end Main count:...7
pool-1-thread-8..is over...
pool-1-thread-9..start Main count:...7
pool-1-thread-9..end Main count:...8
pool-1-thread-9..is over...
pool-1-thread-10..start Main count:...8
pool-1-thread-10..end Main count:...9
pool-1-thread-10..is over...
main thread end... // The main thread ends when all threads finish executing 

The console prints the output above after waiting for 5 seconds. The reason is that all the threads started with 1 concurrent operation will wait for 5 seconds, so it looks like the whole process only waited for 5 seconds, which is 1 concurrent operation

Conclusion:

1. Differences between the execute() method and the submit() method provided by ExecutorService:

The a.execute () method only accepts instances of type Runnable, so it can't get the return value, and it can't dynamically get the thread execution

The b.submit () method accepts the Runnable and Callable instances and returns an Future instance, while the get() method of the Future instance gets the return value of the thread execution and throws a thread execution exception. So you can use the submit() method if you want to get results from thread execution and be able to handle exceptions that might occur during thread execution, or if you want to cancel thread execution in the middle of the process

2. It can be seen from the output that the main method (main thread) ends after the execution of all threads, for the following reasons:

a. Gets the Future instance through the submit() method, and gets the thread return result through the get() method of the Future instance, while the get() method of the Future instance waits for the thread to finish executing before returning, so the main method will wait for all the child threads to finish

b. If you remove the for loop marked in red above, the main method (the main thread) ends prematurely, instead of waiting for all the child threads to finish

Supplement:

1. When multiple threads execute concurrently, if one of them has an exception and is not processed, the thread will automatically stop execution, but the other threads will still execute normally. This is why tomcat can continue to provide services when the request for tomcat is abnormal.

2. tomcat provides a thread pool and a waiting pool. Each time a request comes in, a new thread will be restarted to process the request.


Related articles: