6, Java thread pool

Posted by gogul on Sat, 09 Oct 2021 07:31:52 +0200

6.1 why use thread pool?

6.2 how to use thread pool

Tool class of thread pool:

  • Arrays: tool class for arrays
  • Collections: tool classes for collections
  • Executors: tool class of thread pool

6.2.1 architecture description of thread pool

The thread pool in Java is implemented through the Executor framework, which uses Executor, Executors, ExecutorService and ThreadPoolExecutor

6.2.2 creating thread pools

  • Executors.newFixedThreadPool(int) creates a thread pool with a specified number of threads

  • Executors.newSingleThreadExecutor() creates a thread pool with only one thread

  • Executors.newCachedThreadPool() creates new threads as needed, which can be expanded

Executors.newFixedThreadPool(int)

public class MyThreadDemo {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(5); //There are 5 working threads in a pool, which is similar to a bank with 5 acceptance windows
       try {
           //It is simulated that 10 customers come to the bank to handle business. At present, there are 5 staff in the pool to provide services
           for (int i = 1; i < 10; i++) {
               threadPool.execute(()->{
                   System.out.println(Thread.currentThread().getName()+" Handle the business");
               });
           }
       }catch (Exception e){
           e.printStackTrace();
       }finally {
            threadPool.shutdown();
       }

    }
}
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-4 Handle the business
pool-1-thread-2 Handle the business
pool-1-thread-2 Handle the business
pool-1-thread-5 Handle the business
pool-1-thread-3 Handle the business
pool-1-thread-4 Handle the business
pool-1-thread-1 Handle the business

Note: the thread pool has its own name

Executors.newSingleThreadExecutor()

public class MyThreadDemo {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newSingleThreadExecutor(); //y one pool has one worker thread, which is similar to a bank with one acceptance window
        try {
           //It is simulated that 10 customers come to the bank to handle business. At present, there is a staff member in the pool to provide services
           for (int i = 1; i < 10; i++) {
               threadPool.execute(()->{
                   System.out.println(Thread.currentThread().getName()+" Handle the business");
               });
           }
       }catch (Exception e){
           e.printStackTrace();
       }finally {
            threadPool.shutdown();
       }

    }
}
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-1 Handle the business

Executors.newFixedThreadPool(int) problem: suppose a thread pool with 5 threads is created. If only 2 threads access it, it will be wasted

Executors.newSingleThreadExecutor() problem: suppose a thread pool with one thread is created. If multiple threads access it, it will cause waste

Executors.newCachedThreadPool() can solve the above problems and create dynamically

Executors.newCachedThreadPool()

public class MyThreadDemo {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool(); //A pool of N worker threads is similar to a bank with n acceptance windows
        try {
           //It is simulated that 10 customers come to the bank to handle business. At present, there are N staff in the pool to provide services
           for (int i = 1; i < 10; i++) {
               threadPool.execute(()->{
                   System.out.println(Thread.currentThread().getName()+" Handle the business");
               });
           }
       }catch (Exception e){
           e.printStackTrace();
       }finally {
            threadPool.shutdown();
       }

    }
}
pool-1-thread-2 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-3 Handle the business
pool-1-thread-4 Handle the business
pool-1-thread-5 Handle the business
pool-1-thread-1 Handle the business
pool-1-thread-3 Handle the business
pool-1-thread-2 Handle the business
pool-1-thread-4 Handle the business

6.2.3 underlying principle of ThreadPoolExecutor

6.3 7 important parameters of thread pool

  1. corePoolSize: the number of resident core threads in the thread pool. A minimum number of threads will be maintained in the thread pool. Even if these threads are idle, they will not be destroyed unless allowCoreThreadTimeOut is set
  2. maximumPoolSize: the maximum number of threads that can be executed simultaneously in the thread pool. This value must be greater than or equal to 1
  • CPU intensive programs: maximumPoolSize is set to the number of cores. Runtime.getRuntime().availableProcessors() gets the number of cores
  • I/O-Intensive programs: it is best to set maximumPoolSize to twice the number of CPU cores
  1. keepAliveTime: the survival time of redundant idle threads. When the number of threads in the current pool exceeds corePoolSize, when the idle time reaches keepAliveTime, the redundant threads will be destroyed until only corePoolSize threads are left
  2. Unit: the measurement unit of idle thread survival time, keepAliveTime
  3. workQueue: task queue, a task submitted but not yet executed
  4. threadFactory: the factory used by thread factory when creating a new thread. It can be used to set the thread name, whether it is a daemon thread, etc
  5. handler: reject policy, which indicates how to reject the runnable request execution when the queue is full and the worker thread is greater than or equal to the maximum poolsize of the thread pool

Explanation:

Suppose a bank outlet has 3 permanent core poolsize. If many customers suddenly come to handle business, customers who cannot handle business in time will be asked to queue in the work queue. If the waiting area is also full, increase the number of windows to 5 (maximum poolsize). If five windows are full and the waiting area is full, the door closes and the handler is refused. If there are less than 3 customers in a period of time (keepAliveTime), at this time, three windows are enough. Reduce the five windows to three, that is, the idle thread is inactivated.

6.4 working principle of thread pool bottom layer

6.5 which is used for the line pass pool? How to set reasonable parameters in production?

6.5.1 rejection policy of thread pool

What is it?

The waiting queue is full and no new tasks can be filled. At the same time, the max thread in the thread pool has reached and cannot continue to serve new tasks. This requires the rejection policy mechanism to deal with this problem reasonably.

JDK built-in rejection policy

  • Abortpolicy (default): throw the RejectedExecutionException exception directly to prevent the system from running normally

  • CallerRunsPolicy: caller run, a kind of adjustment mechanism, which neither discards tasks nor throws exceptions, but backs some tasks back to the caller, so as to reduce the traffic of new tasks.

  • DiscardPolicy: this policy silently discards the tasks that cannot be processed, and does not process them or throw exceptions. If the loss of tasks is allowed, this is the best policy.

  • DiscardOldestPolicy: discards the longest waiting task in the queue, then adds the current task to the queue and tries to submit the current task again

6.5.2 which of the three methods to create thread pool is used more? Not at all

Alibaba Development Manual

6.5.3 custom thread pool

If the number of threads exceeds maximumPoolSize+workQueue when using AbortPolicy rejection policy, an error will be reported

public class MyThreadDemo {
    public static void main(String[] args) {
        
        ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        try {
            for (int i = 0; i < 9; i++) {
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+" Handle the business");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}

When the CallerRunsPolicy rejection policy is used, if the number of threads exceeds maximumPoolSize+workQueue, it will be rolled back to the caller for running

public class MyThreadDemo {
    public static void main(String[] args) {
        
        ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());
      .....
      Omitted, ibid
    }
}

When the DiscardPolicy rejection policy is used, if the number of threads exceeds maximumPoolSize+workQueue, the threads that cannot be processed are discarded

public class MyThreadDemo {
    public static void main(String[] args) {
        
        ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardPolicy());
      .....
      Omitted, ibid
    }
}

Only 8 tasks were run, and one task was abandoned

When using the DiscardOldestPolicy rejection policy, if the number of threads exceeds maximumPoolSize+workQueue, the longest waiting task in the queue will be discarded

public class MyThreadDemo {
    public static void main(String[] args) {
        
        ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy());
      .....
      Omitted, ibid
    }
}

Topics: Java Eclipse Hibernate