1 ThreadPoolExecutor
Java is a language that naturally supports concurrency. Supporting concurrency means multithreading. Frequent creation of threads consumes a lot of resources in high concurrency and large amount of data, because Java provides a thread pool. Before JDK1.5, the use of thread pool was very simple, but after JDK1.5, it has been greatly improved. After JDK 1.5, java.util.concurrent package is added. The addition of java.util.concurrent package helps developers to develop concurrent programs and solve concurrent problems. This article mainly introduces the Executor interface under the contract. Although the Executor interface is a very old interface (JDK 1.5 released in 2004), many programmers are not familiar with some of its principles. Therefore, this article is written to introduce the Executor interface and consolidate their knowledge.
The top-level implementation of the Executor framework is the ThreadPoolExecutor class. The newScheduledThreadPool, newFixedThreadPool and newCachedThreadPool methods provided in the Executors factory class are actually just different constructor parameters of ThreadPoolExecutor. By passing in different parameters, we can construct a thread pool suitable for different application scenarios. How is the underlying principle implemented? This article will introduce the running process of the thread pool Executor thread pool.
- corePoolSize: the size of the core pool. When a task comes, a thread will be created to execute the task. When the number of threads in the thread pool reaches corePoolSize, the task will be put into the cache queue
- maximumPoolSize: the maximum number of threads in the thread pool, which indicates the maximum number of threads that can be created in the thread pool;
- keepAliveTime: indicates how long a thread can stay for at most when there is no task to execute.
- Unit: the time unit of the keepAliveTime parameter. There are 7 values. There are 7 static attributes in the TimeUnit class:
2 four ways to create thread pool
Java provides four kinds of thread pools through Executors (jdk1.5 and contract), which are:
- newCachedThreadPool creates a cacheable thread pool. If the length of the thread pool exceeds the processing requirements, idle threads can be recycled flexibly. If there is no recyclable thread, a new thread can be created.
- newFixedThreadPool creates a fixed length thread pool, which can control the maximum concurrent number of threads. The exceeded threads will wait in the queue.
- New scheduledthreadpool creates a fixed length thread pool that supports scheduled and periodic task execution.
- The new single thread executor creates a single threaded thread pool, which only uses unique worker threads to execute tasks and ensures that all tasks are executed in the specified order (FIFO, LIFO, priority).
2.1 Executors.newCachedThreadPool()
public static ExecutorService newCachedThreadPool()
Create a thread pool that creates new threads as needed, but reuse them when previously constructed threads are available. For programs that perform many short-term asynchronous tasks, these thread pools usually improve program performance. Calling execute will reuse the previously constructed thread if it is available. If an existing thread is not available, a new thread is created and added to the pool. Terminate and remove threads that have not been used for 60 seconds from the cache. As a result, a pool of threads that remain idle for a long time will not use any resources. Note that you can use the ThreadPoolExecutor construction method to create a thread pool with similar properties but different details, such as the timeout parameter.
Create a cacheable thread pool. If the length of the thread pool exceeds the processing requirements, idle threads can be recycled flexibly. If there is no recyclable thread, a new thread can be created. The sample code is as follows:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author yang */ public class ThreadPoolExample { public static void main(String[] args) throws InterruptedException { /** * Create CachedThreadPool */ ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; TimeUnit.SECONDS.sleep(2); executorService.execute( () -> { System.out.println("task: " + index); }); } executorService.shutdown(); } }
Launch program, console printing:
task: 0 task: 1 task: 2 task: 3 task: 4 task: 5 task: 6 task: 7 task: 8 task: 9
Summary: the thread pool is infinite. When the second task is executed, the first task has been completed, and the thread executing the first task will be reused instead of creating a new thread every time.
4.2 Executors.newFixedThreadPool(3)
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author yang */ public class ThreadPoolExample { public static void main(String[] args) throws InterruptedException { /** * Create FixedThreadPool */ ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int index = i; TimeUnit.SECONDS.sleep(2); executorService.execute( () -> { System.out.println("task: " + index); }); } executorService.shutdown(); } }
Launch program, console printing:
task: 0 task: 1 task: 2 task: 3 task: 4 task: 5 task: 6 task: 7 task: 8 task: 9
4.3 Executors.newSingleThreadExecutor()
Create a single threaded pool, which only uses unique worker threads to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority). The sample code is as follows:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author yang */ public class ThreadPoolExample { public static void main(String[] args) throws InterruptedException { /** * Create singlethreadexector */ ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; TimeUnit.SECONDS.sleep(2); executorService.execute( () -> { System.out.println("task: " + index); }); } executorService.shutdown(); } }
Launch program, console printing:
task: 0 task: 1 task: 2 task: 3 task: 4 task: 5 task: 6 task: 7 task: 8 task: 9
4.4 Executors.newScheduledThreadPool(1)
Create a fixed length thread pool to support scheduled and periodic task execution. The example code of delayed execution is as follows:
import java.util.Date; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * @author yang */ public class ThreadPoolExample { public static void main(String[] args) { ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); executorService.scheduleAtFixedRate(() -> { System.out.println("schedule run"); }, 1, 3, TimeUnit.SECONDS); Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("schedule run"); } }, new Date(), 5 * 1000); } }
Launch program, console printing:
schedule run schedule run schedule run schedule run schedule run ......