Benefits of the thread pool
1. Threads are scarce resources, and using a thread pool can reduce the number of times a thread is created and destroyed, and each worker thread can be reused.
2, according to the System's ability to withstand, adjust the number of worker threads in the thread pool, to prevent the server crashes because of excessive memory consumption.
Creation of the thread pool
1 public Threadpoolexecutor (int corepoolsize,2 int maximumpoolsize,3 long keepalivetime,4 timeunit unit,5 blockingqueue<runnable> workQueue,6
corepoolsize: Thread pool Core thread count
Maximumpoolsize: thread pool Maximum number of threads
Keepalivertime: maximum surviving time for idle extra threads when the number of active threads is greater than the number of core threads
Unit: Units of survival time
WorkQueue: Queue to hold tasks
Handler: handlers for tasks with super-outgoing range and queue capacity
The implementation principle of thread pool
To submit a task to the thread pool, the processing flow of the thread pools is as Follows:
1. Determine if the core thread constructor is executing a task, and if it is not (the core thread is idle or the core thread is not created) a new worker thread is created to perform the Task. If the core threads are performing tasks, go to the next process.
2. The thread pool determines whether the work queue is full, and if the work queue is not full, the newly submitted task is stored in this task Column. If the work queue is full, go to the next process.
3. Determine if thread constructor threads are working, and if not, create a new worker thread to perform the Task. If it is full, then give the saturation policy to handle the Task.
Source code interpretation of thread pool
1, Threadpoolexecutor's Execute () method
1 public voidExecute (Runnable command) {2 if(command = =NULL)3 Throw NewNullPointerException ();
Join a task to a queue if the number of threads is greater than or equal to the number of basic threads or thread creation fails4 if(poolsize >= corepoolsize | |!addifundercorepoolsize (COMMAND)) {
Thread pool is running and joining queue succeeds5 if(runstate = = RUNNING &&Workqueue.offer (COMMAND)) {6 if(runstate! = RUNNING | | poolsize = = 0)7 ensurequeuedtaskhandled (command);8 }
Thread pool is not running or fails to join the queue, create the threads (non-core threads created)9 Else if(!addifundermaximumpoolsize (COMMAND))
Failed to create thread, the way to take blocking processingTenReject (command);//is shutdown or saturated one } a}
2. How to create a thread:addifundercorepoolsize (command)
1 Private Booleanaddifundercorepoolsize (Runnable firsttask) {2Thread T =NULL;3 FinalReentrantlock Mainlock = this. mainlock;4 Mainlock.lock ();5 Try {6 if(poolsize < corepoolsize && Runstate = =RUNNING)7t =Addthread (firsttask);8}finally {9 Mainlock.unlock ();Ten } one if(t = =NULL) a return false; - T.start (); - return true; the}
Let's focus on line 7th:
1 PrivateThread addthread (Runnable firsttask) {2Worker W =NewWorker (firsttask);3Thread T =Threadfactory.newthread (w);4 if(t! =NULL) {5W.thread =t;6 Workers.add (w);7 intNT = + +poolsize;8 if(nt >Largestpoolsize)9Largestpoolsize =nt;Ten } one returnt; a}
Here the threads are encapsulated into worker threads and put into the worker group, the worker class method of the Run Method:
public void run () { try {Runnable task = firsttask; Firsttask = null ; while (task! = null | | (task = Gettask ())! = null = null ; }} finally {workerdone ( this
After the worker finishes the task, it also loops through the Gettask method to get the task in the Task force to Execute.
We use a program to see how the thread pool works:
1. Create a thread
1 public classThreadpooltestImplementsRunnable2 {3 @Override4 public voidRun ()5 {6 Try7 {8Thread.Sleep (300);9 }Ten Catch(interruptedexception E) one { a e.printstacktrace (); - } - } the}
2. Thread pool loop runs 16 threads:
1 public Static voidmain (string[] Args)2 {3linkedblockingqueue<runnable> queue =4 NewLinkedblockingqueue<runnable> (5);5Threadpoolexecutor ThreadPool =NewThreadpoolexecutor (5, 10, 60, timeunit.seconds, queue);6 for(inti = 0; I < 16; i++)7 {8 Threadpool.execute (9 NewThread (NewThreadpooltest (), "Thread". concat (i + "")));TenSystem.out.println ("number of threads active in thread pool:" +threadpool.getpoolsize ()); one if(queue.size () > 0) a { -System.out.println ("number of blocked threads in the----------------queue" +queue.size ()); - } the } - Threadpool.shutdown (); -}
Execution Result:
Number of threads active in thread Pool: 1number of active threads in the thread pool:2number of active threads in the thread pool:3number of active threads in the thread pool:4number of active threads in the thread pool:5number of active threads in the thread pool:5----------------number of blocked threads in the queue 1 threads active in the thread pool:5----------------number of blocked threads in the queue 2 threads active in the thread pool:5----------------number of blocked threads in the queue 3 threads active in the thread pool:5----------------number of blocked threads in the queue 4 threads active in the thread pool:5----------------number of blocked threads in the queue 5 threads active in the thread pool:6----------------number of blocked threads in the queue 5 threads active in the thread pool:7----------------number of blocked threads in the queue 5 threads active in the thread pool:8----------------number of blocked threads in the queue 5 threads active in the thread pool:9----------------number of blocked threads in the queue 5 threads active in the thread pool:ten----------------number of blocked threads in queue 5Exception in thread"main" Java.util.concurrent.RejectedExecutionException:Task thread[thread15,5,main] rejected from [email protected][ Running, Pool size = ten, Active threads = ten, queued tasks = 5, Completed tasks = 0] at Java.util.concurrent.threadpoolexecutor$abortpolicy.rejectedexecution (threadpoolexecutor.java:2047) at Java.util.concurrent.ThreadPoolExecutor.reject (threadpoolexecutor.java:823) at Java.util.concurrent.ThreadPoolExecutor.execute (threadpoolexecutor.java:1369) at Test. Threadtest.main (threadtest.java:17)
From the results you can see:
1. The thread pool created is configured as follows: the number of core threads is 5, the total number of threads is 10, and the queue length is 5.
2. We use the Queue.size () method to get the number of tasks in the work Queue.
3, operating Principle:
Starting with the creation of a new thread, the number of core threads reached 5, after the new task came in and no longer create a new thread, instead of adding the task to the work queue, the task queue reached 5, The new task will create a new normal thread, until the thread pool reaches the maximum number of threads 10, Subsequent tasks are handled according to the configured saturation Policy. We do not have a specific configuration here, using the default configuration Abortpolicy: throws an exception directly.
of course, in order to achieve the effect I need, the above thread processing task is to take advantage of sleep causes the thread is not released!!!
rejectedexecutionhandler: Saturation Strategy
When the queue and thread pool are full, indicating that the thread pools are saturated, a special policy must be taken for the newly submitted tasks to be Processed. The default configuration for this policy is abortpolicy, which indicates that a new task cannot be processed and throws an Exception. Java provides 4 of policies:
1. abortpolicy: Throw exception directly
2. Callerrunspolicy: run the task only with the thread where the call is located
3. Discardoldestpolicy: discards the most recent task in the queue and executes the current Task.
4, discardpolicy: do not handle, Discard.
We now use the fourth strategy to deal with the above program:
1 public Static voidmain (string[] Args)2 {3linkedblockingqueue<runnable> queue =4 NewLinkedblockingqueue<runnable> (3);5Rejectedexecutionhandler handler =NewThreadpoolexecutor.discardpolicy ();6 7Threadpoolexecutor ThreadPool =NewThreadpoolexecutor (2, 5, 60, timeunit.seconds, queue,handler);8 for(inti = 0; I < 9; i++)9 {Ten Threadpool.execute ( one NewThread (NewThreadpooltest (), "Thread". concat (i + ""))); aSystem.out.println ("number of threads active in thread pool:" +threadpool.getpoolsize ()); - if(queue.size () > 0) - { theSystem.out.println ("number of blocked threads in the----------------queue" +queue.size ()); - } - } - Threadpool.shutdown (); +}
Execution Result:
Number of threads active in the thread pool:12 2----------------2----------------2----------------3 ----------------4----------------5----------------5----------------number of blocked threads in the queue 3
Once the discard strategy is used, no exception is thrown, but it is discarded directly. In some important scenarios, logging can be used or stored in a database, and should not be discarded directly.
There are two ways to set a policy:
1.
Newnew threadpoolexecutor (2, 5, timeunit.seconds, queue,handler);
2.
New Threadpoolexecutor (2, 5,timeunit.seconds, queue); Threadpool.setrejectedexecutionhandler (new threadpoolexecutor.abortpolicy ());
Java thread pool principle of a detailed