This is the 16th day of my participation in the Gwen Challenge.More article challenges

Thread pool introduction:

A thread pool is a collection of threads that are created first, called a thread pool. Using a thread pool is a good way to improve performance, the thread pool at system startup is to create a large number of idle threads, program will be a task to the thread pool, the thread pool will start a thread to execute this task, after the execution, the thread will not die, but again returned to the thread pool become idle, waiting for the next mission.

Thread pool 7 parameters:

  1. CorePoolSize: number of core threads
  2. MaximumPoolSize: indicates the maximum number of threads
  3. KeepAliveTime: Excess threads are destroyed when the time is longer than the idle time
  4. Unit: time unit
  5. WorkQueue: indicates a task queue
  6. ThreadFactory: a threadFactory
  7. RejectedExecutionHandler: reject the policy

How to configure the appropriate thread pool:

We all know that the thread pool has its core number of threads and maximum number of threads, etc. When we customize the thread pool, these need to be defined by ourselves, so how to define the number of threads in the thread pool, we usually divide the thread pool into the following three types:

  1. CPU intensive task

Use as small a thread pool as possible, typically number of CPU cores +1. Cpu-intensive tasks cause high CPU usage. If too many threads are enabled, excessive CPU switchover may occur.

  1. IO intensive task

You can use a slightly larger thread pool, typically 2*CPU cores. IO intensive tasks have low CPU usage. Therefore, you can make full use of CPU time by allowing other threads to handle other tasks while waiting for I/OS.

  1. Mixed task
  1. Tasks can be divided into IO – intensive and CPU – intensive tasks and then handled in separate thread pools. As long as the execution time of the two tasks is similar, it will be more efficient than serial execution.
  2. If there is a data-level difference in the execution time of the two tasks after partitioning, it is meaningless to split them.
  3. Since the first task has to wait for the later task, the final time still depends on the later task, plus the cost of task splitting and merging, which is not worth the cost.

Thread pool execution methods: execute() and submit() :

  1. Execute (), to execute one

Task, no return value. Submit (), submit a thread task, return value.

  1. Submit (Callable Task) gets its return value through future.get() (block until the task completes). Generally, FutureTask and Callable are used together (as shown in IntentService).
  2. Submit (Runnable task, T result) can indirectly obtain the return value of the thread through the incoming carrier result.
  3. Submit (Runnable task) returns no value, even if the return value is null.
  4. The future. get method blocks the thread that fetched the result, wakes it up, and returns the result after it completes execution.

Code examples:

public class WatcherThreadPoolExecutor extends ThreadPoolExecutor { private String watcherName; public WatcherThreadPoolExecutor(String watcherName, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); this.watcherName = watcherName; } public <T> Future<T> submit(Callable<T> task) { monitor(); return super.submit(Tracer.wrap(task)); } public <T> Future<T> submit(Runnable task, T result) { monitor(); return super.submit(Tracer.wrap(task), result); } public Future<? > submit(Runnable task) { monitor(); return super.submit(Tracer.wrap(task)); } private void monitor() {log.info("{}- queue remaining :{}", watcherName, this.getQueue().remainingCapacity()); }}Copy the code

Thread pool status volatile int runState;

  • static final int RUNNING = 0;
  • static final int SHUTDOWN = 1;
  • static final int STOP = 2;
  • static final int TERMINATED = 3;
  1. When a thread pool is created, it is initially in the RUNNING state.
  2. If the shutdown() method is called, the thread pool is shutdown and cannot accept new tasks. It waits for all tasks to complete.
  3. If the shutdownNow() method is called, the thread pool is stopped. The thread pool cannot accept new tasks and attempts to terminate ongoing tasks.
  4. The thread pool is set to TERMINATED when it is SHUTDOWN or stopped and all worker threads have been destroyed, the task cache queue has been emptied, or execution has ended.

Execute (); submit ();

public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize || ! addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState ! = RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (! addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated } }Copy the code

Principle analysis :(essentially a singleton pattern)

public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize || ! addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState ! = RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (! addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or capitalized}} (substance as a singleton) 1. (the command = = null) whether to submit task is empty, or flip a null pointer (2) poolSize > = corePoolSize | |! AddIfUnderCorePoolSize (command) addIfUnderCorePoolSize(command) addIfUnderCorePoolSize(command) addIfUnderCorePoolSize(command) addIfUnderCorePoolSize 2.1: AddIfUnderCorePoolSize (command) if addIfUnderCorePoolSize(command) returns false if addIfUnderCorePoolSize(command) returns false if addIfUnderCorePoolSize(command) returns false if addIfUnderCorePoolSize(command) returns true if addIfUnderCorePoolSize(command) returns false then addIfUnderCorePoolSize(command Workqueue. offer(command) Checks whether the current thread pool is in the RUNNING state. Yes -> Put the current thread pool into the cache queue. If the current thread pool is not in the RUNNING state or the task fails to put the cache queue, Perform addIfUnderMaximumPoolSize (command) method (as the name implies the add maximum thread). 4. Reject (command) if the execution addIfUnderMaximumPoolSize methods fail, then reject () method for mission refused to deal with 5. RunState! = RUNNING | | poolSize = = 0 the judge is to prevent the add this task into the task cache queue at the same time Other threads suddenly call shutdown or shutdownNow method closed thread pool an emergency measures. 6. EnsureQueuedTaskHandled (command) If it's done: Make sure the task added to the task cache queue is handled.Copy the code

The principle is shown as follows:Task cache queue and queuing policy:

The workQueue is of type BlockingQueue, which can be of one of the following types:

  • ArrayBlockingQueue: array-based first-in, first-out queue that must be created with a specified size;
  • LinkedBlockingQueue: a first in, first out queue based on a list, default to integer.max_value if the queue size is not specified when created;
  • SynchronousQueue: This queue is special in that it does not hold submitted tasks and instead creates a new thread to execute the new tasks.

Task rejection Policy:

  • ThreadPoolExecutor. AbortPolicy: discard task and throw RejectedExecutionException anomalies.
  • ThreadPoolExecutor. DiscardPolicy: discard task too, but I don’t throw an exception.
  • ThreadPoolExecutor. DiscardOldestPolicy: discard queue in front of the task, and then to try to perform a task (repeat)
  • ThreadPoolExecutor. CallerRunsPolicy: handle the tasks by the calling thread

Thread pool closure:

  • Shutdown () : The thread pool is not terminated immediately, but is not terminated until all tasks in the task cache queue have completed, but no new tasks are accepted
  • ShutdownNow () : Immediately terminates the thread pool and attempts to interrupt tasks in progress, and empties the task cache queue to return tasks that have not yet been executed

Ok! Today to share this end, I hope it can be helpful to you, there are wrong places I hope you can put forward, grow together;

Neat makes for great code, and there’s only so much detail