A list,

  • What is a thread pool?

You’ve probably heard of the concept of a pool, which is basically a container with a lot of things in it that you can grab and use. Java has thread pools, connection pools, and so on. Thread pool is to create some idle threads when the system starts or instantiates the pool, and wait for the work scheduling. After the task is executed, the threads will not be destroyed immediately, but will be idle again, waiting for the next scheduling.

  • How does a thread pool work?

In the thread pool programming mode, tasks are not submitted directly to the thread, but to the pool. After receiving the task, the thread pool will look for free threads. If there are free threads, it will allocate them to execute. If there are no free threads, it will enter the waiting queue and continue to wait for free threads. If the maximum number of accepted jobs is exceeded, a thread pool rejection policy is triggered.

  • Why use thread pools?

The creation and destruction of threads consumes a lot of resources, and repeated creation and destruction are obviously unnecessary. And the nice thing about a pool is that it responds quickly and takes care of itself when needed, so there’s no waiting time for creation. Thread pools manage the number of threads within the system, as well as scheduling.

Introduction to common thread pools

The Java class ExecutorService is a parent interface to the thread pool, not a top-level interface. Any of the four common thread pool types can be ExecutorService.

  • A single thread pool Executors. NewSingleThreadExecutor ()

There is only one internal thread to schedule work, which can guarantee the execution order of tasks (FIFO,LIFO)

package com.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; Public class PoolTest {public static void main(String[] args) {// Create a single thread pool singleThreadExecutor = Executors.newSingleThreadExecutor(); List<String> list = new ArrayList<String>(); list.add("first");
		list.add("second");
		list.add("third"); List. The forEach (o - > {/ / traverse collection submitting singleThreadExecutor. Execute (newRunnable() {

				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + ":"+ o); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}}); }); }}Copy the code

Execution Result:

pool-1-thread-1 : first

pool-1-thread-1 : second

pool-1-thread-1 : third

  • Can be cached thread pool Executors. NewCachedThreadPool ()

If no thread is available in the pool, create a new thread in the pool. The maximum number of threads in the pool can be cached is integer.max_value. It is often used to run short execution times and frequently used tasks.

package com.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; Public class PoolTest {public static void main(String[] args) {// Create an ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); List<String> list = new ArrayList<String>(); list.add("first");
		list.add("second");
		list.add("third"); List. ForEach (o -> {try {// interval 3s thread.sleep (3000); } catch (InterruptedException e) { e.printStackTrace(); } // Iterate through the collection commit task cachedThreadPool.execute(new)Runnable() {

				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + ":"+ o); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}}); }); }}Copy the code

Execution Result:

pool-1-thread-1 : first

pool-1-thread-1 : second

pool-1-thread-1 : third

Because the interval is long, the next task will run while the previous task has already completed, so the thread can continue to reuse, if the interval is shortened, then some threads will use the new thread to run.

Reduce the wait time for each task from 3s to 1s:

Execution Result:

pool-1-thread-1 : first

pool-1-thread-2 : second

pool-1-thread-1 : third

  • Fixed-length thread pool Executors. NewFixedThreadPool (int nThreads)

Create a thread pool with a fixed number of threads and pass in the parameters manually

package com.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; Public class PoolTest {public static void main(String[] args) {// Create cacheable thread pool fixedThreadPool = Executors.newFixedThreadPool(3); List<String> list = new ArrayList<String>(); list.add("first");
		list.add("second");
		list.add("third");
		list.add("fourth"); List. ForEach (o -> {try {// interval 1s thread. sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // Iterate through the collection commit task fixedThreadPool.execute(newRunnable() {

				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + ":"+ o); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}}); }); }}Copy the code

Execution Result:

pool-1-thread-1 : first

pool-1-thread-2 : second

pool-1-thread-3 : third

pool-1-thread-1 : fourth

  • Thread pool regularly Executors. NewScheduledThreadPool (int corePoolSize)

Create a fixed – length thread pool to support scheduled and periodic task execution

package com.test; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; Public class PoolTest {public static void main(String[] args) {// Create a thread pool of fixed length. ScheduledExecutorService supports scheduled, delayed, and periodic task execution scheduledThreadPool = Executors.newScheduledThreadPool(3); scheduledThreadPool.scheduleAtFixedRate(newRunnable() {

			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName() + ": every 3 seconds after 1 second"); } }, 1, 3, TimeUnit.SECONDS); }}Copy the code

Execution Result:

Pool-1-thread-1: the pool-1-thread-1 command is executed every three seconds

Pool-1-thread-1: the pool-1-thread-1 command is executed every three seconds

Pool-1-thread-2: the command is executed every three seconds after one second

Pool-1-thread-2: the command is executed every three seconds after one second

Pool-1-thread-2: the command is executed every three seconds after one second

Pool-1-thread-2: the command is executed every three seconds after one second

Pool-1-thread-2: the command is executed every three seconds after one second

Custom thread pools

Common constructors:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
Copy the code

Parameter Description:

CorePoolSize Specifies the size of the core thread. If the number of threads is less than corePoolSize, a thread will be created to execute a runnable

2, maximumPoolSize Specifies the maximum number of threads in the workQueue. If the number of threads >= corePoolSize, runnable will be added to the workQueue

KeepAliveTime keepAliveTime, the maximum keepAliveTime for an idle thread whose number is greater than corePoolSize.

4, Unit time unit

5. WorkQueue Stores the blocking queue of tasks

ThreadFactory Specifies the factory that creates the thread

Handler rejects the policy

Task execution sequence:

1. When the number of threads is smaller than corePoolSize, create a thread to execute the task.

2. If the number of threads is greater than or equal to corePoolSize and the workQueue is not full, the thread is added to the workQueue

3. If the number of threads is greater than or equal to corePoolSize and the workQueue is full, a new thread is created for the task and the total number of threads is smaller than maximumPoolSize

Execute handler rejectedExecution when the number of threads is maximumPoolSize and the workQueue is full. That’s the rejection strategy.

ThreadPoolExecutor has four rejection policies by default:

1, new ThreadPoolExecutor. AbortPolicy () throws an exception directly RejectedExecutionException

2, new ThreadPoolExecutor. CallerRunsPolicy () to invoke the run method directly and block the execution

3, new ThreadPoolExecutor. DiscardPolicy () directly discarded later task

4, new ThreadPoolExecutor. DiscardOldestPolicy on queue squadron () the first task

BlockingQueue:

BlockingQueue is a double-buffered queue. BlockingQueue uses two queues internally, allowing two threads to simultaneously store and fetch from the queue. While ensuring concurrency security, the access efficiency of queue is improved.

Common blockingQueues:

  • ArrayBlockingQueue (int I) : Specifies the size of the BlockingQueue, whose construct must specify the size. Its objects are sorted in FIFO order.

  • LinkedBlockingQueue () or (int I) : An unfixed BlockingQueue. If the size is specified, the resulting BlockingQueue has a limited size. The size is not specified, but integer.max_value determines the size. Its objects are sorted in FIFO order.

  • PriorityBlockingQueue () or (int I) : Similar to LinkedBlockingQueue, but the order of its contained objects is determined by the natural order of the objects or by the constructor’s Comparator instead of a FIFO.

  • SynchronizedQueue () : Special BlockingQueue that must alternate put and fetch operations.

package com.test; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; Public class PoolTest {public static void main(String[] args) {// Queue <Runnable> workQueue = new LinkedBlockingDeque<Runnable>(); . / / rejection policies RejectedExecutionHandler handler = new ThreadPoolExecutor AbortPolicy (); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 10, 20, TimeUnit.MILLISECONDS, workQueue, handler); threadPoolExecutor.execute(newRunnable() {

			@Override
			public void run() {
				System.out.println("Custom thread Pool"); }}); }}Copy the code