The thread pool

1. Introduction

The idea of pools, you have connection pools in databases, constant pools in strings, and so on.

In order to “prevent the time loss of connection creation and destruction during use”, we choose to create a part of connections when the service is started for subsequent use, and put them into the pool after use, forming the concept of reuse and the emergence of the pool.

The same is true for thread pools, where a pool is initialized at service startup via Spring or static methods, etc. All subsequent requests are added directly to the pool, and threads in the pool directly execute the tasks added to the pool.

The thread pool has a core thread count, which is the number of threads that a thread has at its inception, and when the core thread count is insufficient to process an incoming task, that task is added to the blocking queue.

When the blocking queue is saturated, the thread pool creates threads again until the maximum number of threads is reached.

If the maximum number of threads has been reached and the task cannot be processed, the task is rejected according to the specified rejection policy.

When the number of tasks is small, the thread is idle, and when the idle time exceeds the maximum we specify, the thread pool will destroy it.


2. Basic parameters of the thread pool

From the above, it is easy to know what parameters a thread pool needs.

First, an initialization thread number, coreSize

  • A blocking queue,BlockingQueue
  • A maximum number of threads,maxSize
  • A rejection strategy,RejectedExecutionHandler
  • A maximum idle time and unit of time,keepAliveTimeandtimeUnit
  • There’s also a thread project that helps us create a threadthreadFactory

These are the seven parameters of a thread pool, from which we build a thread pool

3. Customize the thread pool

This thread pool only simulates the use of four parameters: core thread, maximum thread, and maximum queue length

The task class

public class MyTask implements Runnable{

    int id  ;

    public MyTask(int id) {
 this.id = id;  }   @Override  public void run(a) {  String name = Thread.currentThread().getName();  System.out.println(name+"\ T about to embark on a mission"+id);  try {Thread.sleep(200); }catch(InterruptedException e) {e.printStackTrace(); } System.out.println(name+"\ T has fulfilled its mission");  }   @Override  public String toString(a) {  return "MyTask{" +  "id=" + id +  '} ';  } } Copy the code

Thread class

/ * ** A custom thread* /
public class MyThread extends Thread{
    private String name ;
 private List<Runnable> tasks ;   public MyThread(String name, List<Runnable> tasks) {  this.name = name;  this.tasks = tasks;  }   @Override  public void run(a) {  while(tasks.size()>0) { Runnable remove = tasks.remove(0);  remove.run();  }  } } Copy the code

The thread pool class

/ * ** Custom thread pools* /
public class MyPool {

 private int currentPoolSize ;  private int corePoolSize ;  private int maxPoolSize ;  private int workSize ;  private List<Runnable> tasks = new CopyOnWriteArrayList<>();   public MyPool(int corePoolSize, int maxPoolSize, int workSize) {  this.corePoolSize = corePoolSize;  this.maxPoolSize = maxPoolSize;  this.workSize = workSize;  }   public void sumbit(Runnable runnable){  // If the number of current threads is smaller than the number of core threads  if(tasks.size()>=workSize){  System.out.println("Task dropped");  }else{  tasks.add(runnable);  this.execTask(runnable);  }  }   public void execTask(Runnable runnable){  if(currentPoolSize <= corePoolSize){  new MyThread("Thread"+currentPoolSize,tasks).start();  currentPoolSize++;  }else if(currentPoolSize < maxPoolSize){  new MyThread("Non-core thread"+currentPoolSize,tasks).start();  currentPoolSize++;  }else{  System.out.println(runnable+"Task cached");  }  }  } Copy the code

actuator

public class MyThreadPollTest {
    public static void main(String[] args) {
        MyPool myPool = new MyPool(2.4.20);
        for (int i = 0; i < 30; i++) {
            MyTask myTask = new MyTask(i);
 myPool.sumbit(myTask);  }  } } Copy the code

follower

yTask{id=4} Tasks are cachedMyTask{id=5} Tasks are cachedMyTask{id=6} Tasks are cachedMyTask{id=7} Tasks are cachedMyTask{id=8} Tasks are cachedMyTask{id=9} Tasks are cachedMyTask{id=10} Tasks are cachedMyTask{id=11} Tasks are cachedMyTask{id=12} Tasks are cachedMyTask{id=13} Tasks are cachedMyTask{id=14} Tasks are cachedMyTask{id=15} Tasks are cachedMyTask{id=16} Tasks are cachedMyTask{id=17} Tasks are cachedMyTask{id=18} Tasks are cachedMyTask{id=19} Tasks are cachedThread-3Upcoming mission2 Thread-2Upcoming mission1 Thread-1Upcoming mission0 MyTask{id=20} Tasks are cachedMyTask{id=21} Tasks are cachedMyTask{id=22} Tasks are cachedThread-0Upcoming mission3 MyTask{id=23} Tasks are cachedTask discardedTask discardedTask discardedTask discardedTask discardedTask discardedThread-3Finished the jobThread-3Upcoming mission4 Thread-2Finished the jobThread-2Upcoming mission5 Thread-1Finished the jobThread-1Upcoming mission6 Thread-0Finished the jobThread-0Upcoming mission7 Thread-1Finished the jobThread-3Finished the jobThread-1Upcoming mission8 Thread-3Upcoming mission9 Thread-0Finished the jobThread-2Finished the jobThread-2Upcoming mission10 Thread-0Upcoming mission11 Thread-3Finished the jobThread-1Finished the jobThread-1Upcoming mission12 Thread-3Upcoming mission13 Thread-0Finished the jobThread-0Upcoming mission14 Thread-2Finished the jobThread-2Upcoming mission15 Thread-1Finished the jobThread-1Upcoming mission16 Thread-3Finished the jobThread-3Upcoming mission17 Thread-2Finished the jobThread-0Finished the jobThread-0Upcoming mission19 Thread-2Upcoming mission18 Thread-3Finished the jobThread-1Finished the jobThread-1Upcoming mission21 Thread-3Upcoming mission20 Thread-0Finished the jobThread-0Upcoming mission22 Thread-2Finished the jobThread-2Upcoming mission23 Thread-1Finished the jobThread-3Finished the jobThread-0Finished the jobThread-2Finished the jobCopy the code

4. Java thread pools

Thread architecture diagram


Java provides a Executors class to get some specific threads

4.1 Thread pool without core threads

public static ExecutorService newCachedThreadPool(a) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                60L, TimeUnit.SECONDS,
                                new SynchronousQueue<Runnable>());
    }
 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {  return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  60L, TimeUnit.SECONDS,  new SynchronousQueue<Runnable>(),  threadFactory);  } Copy the code

4.2 Singleton thread pool

This thread pool creates only one core thread

public static ExecutorService newSingleThreadExecutor(a) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1.1.             0L, TimeUnit.MILLISECONDS,
              new LinkedBlockingQueue<Runnable>()));
} public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {  return new FinalizableDelegatedExecutorService  (new ThreadPoolExecutor(1.1. 0L, TimeUnit.MILLISECONDS,  new LinkedBlockingQueue<Runnable>(),  threadFactory));  } Copy the code

4.3 Timing thread Pool

A thread pool that can execute scheduled tasks

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

public static ScheduledExecutorService newScheduledThreadPool(  int corePoolSize, ThreadFactory threadFactory) {  return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);  } Copy the code
  • scheduleAtFixedRateThe interval includes the time to perform the task
  • scheduleWithFixedDelayThe interval does not include the time to execute the task

4.4 ThreadPoolExecutor

This is a thread pool provided by Java, and we often use this custom thread pool directly in development

Construction method:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
 TimeUnit unit,  BlockingQueue<Runnable> workQueue,  ThreadFactory threadFactory,  RejectedExecutionHandler handler) Copy the code

Let’s focus on blocking queues and rejection policies.

4.4.1 Blocking queues

BlockingQueue is an interface. Take a look at its inheritance diagram


  • ArrayBlockingQueueA bounded blocking queue consisting of arrays
  • LinkedBlockingQueueA bounded blocking queue consisting of linked lists
  • SynchronousQueueQueues that do not store elements, but only one queue
  • LinkedBlockingQueueA double-ended bounded queue.
  • PriorityBlockingQueueA bounded queue that supports priority sorting
  • DelayQueueDelayed-unbounded queues implemented using priority queues
  • LinkedTransferQueueAn unbounded blocking queue consisting of a linked list structure

Three ways of execution

  • Throw an exception.The add () and remove ()
java.lang.IllegalStateException
Copy the code
  • Returns Boolean or NULL.offerandpoll
Add backfalse; Remove returnnull
Copy the code
  • The thread is blocked.putandtake
  • Look at the elements that followelementandpeek
4.4.2 Rejection Policy

The default denial strategy for thread pools is to throw an exception directly

There are four rejection policies for thread pools

  • AbortPolicyThrows an exception directly, rejecting the policy by default
  • CallerRunsPolicyReturn the task to the caller for execution, that is, to the thread in the thread pool for execution
  • DiscardPolicyDirect refused to
  • DiscardOldestPolicyTry to dequeue the queue that has waited the longest and add the latest one to the queue
4.4.3 Setting Thread Pool Parameters

According to the 8020 principle, the system generates 100 tasks per second in 80% of the time, and the execution time of a task is 0.1 second. A maximum of 1000 tasks can be generated in a second

  • Number of core threads.100 * 0.1 = 10
  • Task queue length.100 * 2 = 200
  • Maximum number of threads.(Maximum number of tasks - Task queue length) x execution time of a single task (1000-200) x 0.1=800

5. ExecutorService

There is an ExecutorService in the thread pool inheritance architecture above. This is the thread pool interface built into Java

void shutdown(a)Initiates a sequential shutdown that executes previously submitted tasks but does not accept new tasks.List<Runnable> shutdownNow(a)Stop all tasks in progress, pause processing of waiting tasks, and return to the list of tasks waiting to be executed.<T> Future<T> submit(Callable<T> task)Performs a task with a return value that returns a Future object.Future<? >submit(Runnable task)Execute the Runnable task and return a Future representing the task.<T> Future<T> submit(Runnable task, T result)Execute the Runnable task and return a Future representing the task.Copy the code

Previous recommendations:

This article takes you through the architectural thinking of Spring MVC

Mybatis you only know CRUD

You know the IOC structure

This article is formatted using MDNICE