1, Alibaba's code specification:
[mandatory] thread pools are not allowed to be created using Executors, but through ThreadPoolExecutor. This processing method makes the writing students more clear about the running rules of thread pools and avoid the risk of resource depletion.
Note: the disadvantages of the thread pool object returned by Executors are as follows:
1)FixedThreadPool and SingleThreadPool:
The allowed request queue length is integer MAX_ Value, which may accumulate a large number of requests, resulting in OOM. It may also cause stack overflow.
2) CachedThreadPool and ScheduledThreadPool:
The number of threads allowed to create is integer MAX_ Value, a large number of threads may be created, resulting in OOM. It may also cause stack overflow.
Integer.MAX_VALUE
The maximum value of java int type integer is (the 31st power of 2) - 1 = 2147483648 - 1 = 2147483647 (more than 2.1 billion) (int type 4byte (byte) = 32bit (bit) in java)
2, Introduction to ThreadPoolExecutor:
The thread pool class is Java util. concurrent. ThreadPoolExecutor. The common construction methods are:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler)
corePoolSize: the minimum number of threads maintained by the thread pool
maximumPoolSize: the maximum number of thread pool maintenance threads
keepAliveTime: the idle time allowed by thread pool maintenance threads
Unit: the unit of idle time allowed by thread pool maintenance threads
workQueue: the buffer queue used by the thread pool
handler: the processing strategy of the thread pool for rejecting tasks
A task is added to the thread pool through the execute(Runnable) method. The task is a Runnable object, and the execution method of the task is the run() method of the Runnable object.
When a task is added to the thread pool through the execute(Runnable) method:
If the number of threads in the thread pool is less than corePoolSize at this time, even if the threads in the thread pool are idle, a new thread should be created to process the added task.
If the number of threads in the thread pool is equal to corePoolSize at this time, but the buffer queue workQueue is not full, the task is put into the buffer queue.
If the number of threads in the thread pool is greater than corePoolSize, the buffer queue workQueue is full, and the number of threads in the thread pool is less than maximumPoolSize, a new thread is created to process the added task.
If the number of threads in the thread pool is greater than corePoolSize, the buffer queue workQueue is full, and the number of threads in the thread pool is equal to maximumPoolSize, the task is handled through the policy specified by the handler.
That is, the priority of processing tasks is:
The core thread corePoolSize, the task queue workQueue, and the maximum thread maximumPoolSize. If all three are full, the handler is used to process the rejected task.
When the number of threads in the thread pool is greater than corePoolSize, if a thread is idle for more than keepAliveTime, the thread will be terminated. In this way, the thread pool can dynamically adjust the number of threads in the pool.
The optional parameter of unit is Java util. concurrent. Several static properties in timeunit:
NANOSECONDS,MICROSECONDS,MILLISECONDS,SECONDS.
workQueue: Java util. concurrent. Arrayblockingqueue
handler has four options:
ThreadPoolExecutor.AbortPolicy()
Throw Java util. concurrent. Rejectedexecutionexception exception
ThreadPoolExecutor.CallerRunsPolicy()
Retry adding the current task, and he will automatically call the execute() method repeatedly
ThreadPoolExecutor.DiscardOldestPolicy()
Abandon old tasks
ThreadPoolExecutor.DiscardPolicy()
Abandon the current task
3, Usage examples
1 package demo; 2 3 import java.io.Serializable; 4 import java.util.concurrent.ArrayBlockingQueue; 5 import java.util.concurrent.ThreadPoolExecutor; 6 import java.util.concurrent.TimeUnit; 7 8 public class TestThreadPool2 9 { 10 private static int produceTaskSleepTime = 2; 11 private static int produceTaskMaxNumber = 10; 12 13 public static void main(String[] args) 14 { 15 // Construct a thread pool 16 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3), 17 new ThreadPoolExecutor.DiscardOldestPolicy()); 18 19 for (int i = 1; i <= produceTaskMaxNumber; i++) 20 { 21 try 22 { 23 // Generate a task and add it to the thread pool 24 String task = "task@ " + i; 25 System.out.println("put " + task); 26 threadPool.execute(new ThreadPoolTask(task)); 27 28 // Easy to observe, wait for a period of time 29 Thread.sleep(produceTaskSleepTime); 30 } 31 catch (Exception e) 32 { 33 e.printStackTrace(); 34 } 35 } 36 } 37 } 38 39 /** 40 * Tasks performed by thread pool 41 */ 42 class ThreadPoolTask implements Runnable, Serializable 43 { 44 private static final long serialVersionUID = 0; 45 private static int consumeTaskSleepTime = 2000; 46 // Save the data required by the task 47 private Object threadPoolTaskData; 48 49 ThreadPoolTask(Object tasks) 50 { 51 this.threadPoolTaskData = tasks; 52 } 53 54 public void run() 55 { 56 // Processing a task, the processing method here is too simple, just a print statement 57 System.out.println(Thread.currentThread().getName()); 58 System.out.println("start .." + threadPoolTaskData); 59 60 try 61 { 62 // //Easy to observe, wait for a period of time 63 Thread.sleep(consumeTaskSleepTime); 64 } 65 catch (Exception e) 66 { 67 e.printStackTrace(); 68 } 69 threadPoolTaskData = null; 70 } 71 72 public Object getTask() 73 { 74 return this.threadPoolTaskData; 75 } 76 }
Description:
1. In this program, a task is an object of Runnable type, that is, an object of ThreadPoolTask type.
2. Generally speaking, in addition to the processing method, the task also needs to process the data, and the processed data is transmitted to the task through the construction method.
3. In this program, the main() method is equivalent to a cruel leader who sends out many tasks to a hard-working team called threadPool.
There are at least two members in this group. If they are not busy, the task will be placed in the task list.
If there are too many tasks in the backlog to fit the task list (more than 3), hire new team members to help. However, based on the consideration of cost, we can't hire too many team members. At most, we can only hire four.
If the four team members are busy and have a new task, the team will not be able to deal with it. The task will be handled through a strategy. Our way of handling is to keep distributing until we accept the task (more cruel! Hehe).
Because the work of the players is cost effective. If too idle, there is no new mission to 3SECONDS, then some players will be fired. However, for the normal operation of the team, even if the work is idle, the team members can not be less than two.
4. By adjusting the sizes of produceTaskSleepTime and consumeTaskSleepTime, we can control the speed of sending and processing tasks. By changing these two values, we can observe the work of the program at different rates.
5. By adjusting the data referred to in 4, adjusting the task discarding strategy, and replacing the other three strategies, we can see the different processing methods under different strategies.
6. For other usage methods, please refer to the help of jdk, which is easy to understand and use.
1 package demo; 2 3 import java.util.Queue; 4 import java.util.concurrent.ArrayBlockingQueue; 5 import java.util.concurrent.ThreadPoolExecutor; 6 import java.util.concurrent.TimeUnit; 7 8 public class ThreadPoolExecutorTest 9 { 10 11 private static int queueDeep = 4; 12 13 public void createThreadPool() 14 { 15 /* 16 * Create a thread pool. The minimum number of threads is 2 and the maximum number of threads is 4. The idle time of thread pool maintenance threads is 3 seconds, 17 * Using a bounded queue with a queue depth of 4, if the executing program has not been closed, the task at the head of the work queue will be deleted, 18 * Then try to execute the program again (if it fails again, repeat the process), which has controlled the task loading according to the queue depth. 19 */ 20 ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueDeep), 21 new ThreadPoolExecutor.DiscardOldestPolicy()); 22 23 // Add 10 tasks to the thread pool 24 for (int i = 0; i < 10; i++) 25 { 26 try 27 { 28 Thread.sleep(1); 29 } 30 catch (InterruptedException e) 31 { 32 e.printStackTrace(); 33 } 34 while (getQueueSize(tpe.getQueue()) >= queueDeep) 35 { 36 System.out.println("The queue is full. Wait 3 seconds before adding tasks"); 37 try 38 { 39 Thread.sleep(3000); 40 } 41 catch (InterruptedException e) 42 { 43 e.printStackTrace(); 44 } 45 } 46 TaskThreadPool ttp = new TaskThreadPool(i); 47 System.out.println("put i:" + i); 48 tpe.execute(ttp); 49 } 50 51 tpe.shutdown(); 52 } 53 54 private synchronized int getQueueSize(Queue queue) 55 { 56 return queue.size(); 57 } 58 59 public static void main(String[] args) 60 { 61 ThreadPoolExecutorTest test = new ThreadPoolExecutorTest(); 62 test.createThreadPool(); 63 } 64 65 class TaskThreadPool implements Runnable 66 { 67 private int index; 68 69 public TaskThreadPool(int index) 70 { 71 this.index = index; 72 } 73 74 public void run() 75 { 76 System.out.println(Thread.currentThread() + " index:" + index); 77 try 78 { 79 Thread.sleep(3000); 80 } 81 catch (InterruptedException e) 82 { 83 e.printStackTrace(); 84 } 85 } 86 } 87 }