Most of the text is transferred from http://www.cnblogs.com/yydcdut/p/3890893.html
1.Java Thread Pool Fundamentals
The thread pool rationale is that the system starts a number of threads first. and leave these threads in sleep state. When there is a new task, it wakes up one of the sleep threads in the thread pool and lets it handle the task. When the task is finished, the thread is asleep again.
In Java, the main component of the thread pool is worker threads. This type of thread is independent of the runnable and callable tasks it runs, and is often used to run multiple tasks.
The difference between a worker thread and a normal thread is different from the Run method.
The normal thread exits after the thread should run the code, the thread ends, and the Java Virtual Machine reclaims the resources assigned to the thread. The thread object is reclaimed by the garbage collection period. The worker thread that makes up the thread pool is a reusable thread whose run method runs through the specific code of a task and puts itself into sleep instead of ending the thread.
2. The role of the thread pool
The thread pool function is to limit the number of threads running in the system.
According to the environment of the system, the number of threads can be set on their own initiative or manually to achieve the best performance; less waste of system resources, more caused by the system congestion efficiency is not high. Use the thread pool to control the number of threads and other threads to wait. A task executes, and then the first task from the queue starts. If there is no waiting process in the queue, this resource of the thread pool is waiting. When a new task needs to be executed, it is assumed that there are waiting threads in the thread pool to start executing. Otherwise, enter the wait queue.
3. Why Use Threads
① reduces the number of times a thread is created and destroyed, and each worker thread can be reused. You can run multiple tasks.
② can adjust the number of threads in the thread pool based on the ability of the system to withstand. Prevent the server from getting down because it consumes too much memory (each thread needs about 1MB of memory and the more threads are open). The greater the memory consumed, the last crash).
Several important classes in the 4.Concurrent package
The top interface of the thread pool in Java is executor, but strictly speaking executor is not a thread pool. It's just a tool that runs threads. The real thread pool interface is executorservice.
Some of the more important classes:
| Executorservice |
A true thread pool interface |
| Scheduledexecutorservice |
Similar to Timer/timertask, solving problems that require tasks to run repeatedly |
| Threadpoolexecutor |
Default implementation of Executorservice |
| Scheduledthreadpoolexecutor |
Implementation of Scheduledexecutorservice interface for inheriting threadpoolexecutor, and class implementation of periodic task scheduling |
the frame diagram between classes
Threadpoolexecutor Specific explanations
The signature of the complete construction method for Hreadpoolexecutor is:
Threadpoolexecutor (int corepoolsize, int maximumpoolsize, long keepalivetime, timeunit unit, blockingqueue<runnable > WorkQueue, threadfactory threadfactory, Rejectedexecutionhandler handler).
Explanation of the parameters:
corepoolsize -The number of threads saved in the pool. Contains the spare thread.
maximumpoolsize-The maximum number of threads that are agreed in the pool.
KeepAliveTime -When the number of threads is greater than the core. This is the maximum time to wait for a new task before terminating the extra spare thread.
Unit-KeepAliveTime The time units of the number of references.
WorkQueue -the queue used to hold the task before running.
This queue keeps only the runnable tasks that are submitted by the Execute method.
Threadfactory -The factory that the program uses when it creates a new thread.
Handler -the handler that is used when the run is blocked because it exceeds the thread range and queue capacity.
Threadpoolexecutor is the underlying implementation of the Executors class.
In the JDK help documentation, there is a passage:
"It is strongly recommended that the program ape use the more convenient executors factory method Executors.newcachedthreadpool () (without a boundary pool, able to carry out its own active thread recycling), Executors.newfixedthreadpool (int) (fixed-size thread pool) executors.newsinglethreadexecutor () (a single background thread) that defines settings in advance for most usage scenarios. ”
The following describes the source code for several classes:
Executorservice newfixedthreadpool (int nthreads): Fixed size thread pool
public static Executorservice newfixedthreadpool (int nthreads) { return new Threadpoolexecutor (Nthreads, Nthreads, 0L, Timeunit.milliseconds, New linkedblockingqueue<runnable> ()); }
Can see. Corepoolsize and maximumpoolsize are the same size (in fact, they are described later.) Suppose the maximumpoolsize parameter is meaningless if you use an unbounded queue, what is the value table name for KeepAliveTime and unit? --That's the implementation don't want to keep alive. The last Blockingqueue chose Linkedblockingqueue, the linkedblockingqueue has a characteristic, it is unbounded .
Executorservice Newsinglethreadexecutor (): Single thread
public static Executorservice Newsinglethreadexecutor () { return new Finalizabledelegatedexecutorservice ( New Threadpoolexecutor (1, 1, 0L, Timeunit.milliseconds, new Linkedblockingqueue<runnable> ())); }
Executorservice Newcachedthreadpool (): No boundary pool, capable of self-active thread recycling
public static Executorservice Newcachedthreadpool () { return new Threadpoolexecutor (0, Integer.max_value, 60L , Timeunit.seconds, new synchronousqueue<runnable> ()); }
The first is the unbounded thread pool, so we can find maximumpoolsize as Integer.max_value.
followed by the Blockingqueue selection on the use of synchronousqueue. May be a little strange for the blockingqueue, simply said: the Blockingqueue. Each insert operation must wait for the corresponding removal of one thread.
Start with blockingqueue<runnable> workQueue this entry.
In the JDK, the fact has been made clear that there are three types of queue in common.
All blockingqueue can be used to transfer and maintain submitted tasks.
The ability to use this queue to interact with the pool size:
Assuming that the thread executed is less than corepoolsize, executor always prefers to join a new thread without queuing. (assume that the currently executing thread is less than corepoolsize.) The task is not stored at all, added to the queue, but directly copy the guy (thread) to start execution)
Assuming that the thread executing is equal to or more than corepoolsize, executor always prefers to join the request to the queue without joining the new thread .
Assuming that the request cannot be increased by the queue, a new thread is created. Unless this thread is created beyond maximumpoolsize, in such a case. The task will be rejected.
Three types of queue
There are three common strategies for queuing:
Submit directly
The default option for the work queue is synchronousqueue, which will submit tasks directly to the thread without maintaining them.
Here, assuming that there is no thread available to perform the task immediately, the attempt to increase the queue will fail. Therefore, a new thread is constructed.
This policy avoids locking when processing a set of requests that may have internal dependencies.
Direct submissions typically require unbounded maximumpoolsizes to avoid rejecting newly submitted tasks.
When a command is reached continuously with an average of more than the queue can handle. This policy agrees that there is an increase in the likelihood of a line path.
Unbounded queue
Using unbounded queues (for example, linkedblockingqueue that do not have a pre-defined capacity) will cause all corepoolsize threads to be busy while the newer tasks wait in the queue. This way, the created thread will not exceed corepoolsize.
therefore The value of the maximumpoolsize is also invalid.
When each task is completely independent of other tasks. That is, when the task runs independently of each other. Suitable for use with unbounded queues. Like what. In the Web page server. Such a queue can be used to handle transient burst requests, which, when the command is continuously reached with an average of more than the queue can handle, agrees that there is a possibility of an increase in the number of lines.
bounded queues
When a limited maximumpoolsizes is used. Bounded queues (such as Arrayblockingqueue) help prevent resource exhaustion , but may be difficult to adjust and control. Queue size and maximum pool size may need to be compromised: using large queues and small pools minimizes CPU usage, operating system resources, and context switching overhead. However, it may result in manual reduction of throughput. Assume that the task is clogged frequently (e.g.. Assume they are I/O boundaries). The system may schedule time for many other threads that exceed your license.
Using small queues typically requires a large pool size, high CPU utilization, but may encounter unacceptable scheduling overhead, which also reduces throughput.
The choice of Blockingqueue
① uses a direct commit policy, which is also synchronousqueue
First, the synchronousqueue is unbounded. That means there is no limit to his ability to save a few tasks. However, because of the nature of the queue itself, it is necessary to wait for other threads to continue to join after the element has been added . Not the core thread here is the newly created thread, but let's just think of it. The following scenario.
Let's use the parameters to construct the Threadpoolexecutor:
New Threadpoolexecutor ( 2, 3, Timeunit.seconds, new synchronousqueue<runnable> (), new Recorderthreadfactory ("Cookierecorderpool"), new Threadpoolexecutor.callerrunspolicy ());
When a core thread already has 2 executing.
1. A task continues at this point (a), executor always prefers to join a request to a queue, based on the assumption that the thread executing is equal to or more than corepoolsize.instead of adding new threads。 ", so a is added to the queue.
2. Another task (B), and the Core 2 threads are not finished yet. OK, the next first try to describe the narrative in 1, but because of the use of synchronousqueue, so must not be added.
3. At this point, it satisfies the above mentioned "assuming that the request cannot be added to the queue, create a new thread." Unless this thread is created to exceed maximumpoolsize, in such a case, the task will be rejected. ”。 So it is bound to create a new thread to perform this task.
4, temporary can also, but assume that these three tasks are not finished. Two consecutive missions, the first to join the queue, the latter one? The queue cannot be inserted, and the number of threads has reached maximumpoolsize. So it's just good to run the exception strategy.
so the use of synchronousqueue usually requires that the maximumpoolsize be unbounded , so that this can be avoided (assuming that you want to limit the use of bounded queues).
It is very clear what is written in the JDK using synchronousqueue: This policy avoids locking when processing a set of requests that may have internal dependencies.
What do you mean? Suppose your task is A1. A2 has an internal association. A1 need to run first, then submit A1 first. Then submit A2, when using synchronousqueue we can guarantee that A1 must first be run, before A1 is run, A2 cannot join into the queue.
The ② uses a unbounded queue policy. namely Linkedblockingqueue
This is the most complex use. So the JDK is not recommended to use also some reason. Compared with the above, the biggest feature is the ability to prevent the depletion of the situation occurs.
For example. See, for example, the following construction methods:
New Threadpoolexecutor ( 2, 4, Timeunit.seconds, new Arrayblockingqueue<runnable> (2), new Recorderthreadfactory ("Cookierecorderpool"), new Threadpoolexecutor.callerrunspolicy ());
If. All the tasks will never run out.
For the first, a, B to execute directly. Next, let's say c,d. They will be placed in the queue, assuming the next e,f, add the thread to execute e,f. But assuming the task again, the queue can no longer accept, the number of threads has reached the maximum limit. Therefore, a deny policy is used to process it.
KeepAliveTime
The explanation in the JDK is that when the number of threads is greater than the core. This is the maximum time to wait for a new task before terminating the extra spare thread.
A bit of a mouthful, in fact this is not difficult to understand, in the use of "pool" in the application, most of them have similar parameters need to be configured. For example, database connection pool, maxidle in DBCP. Minidle the number of references.
What do you mean? Then the above explanation. Later, the workers sent to the boss were always "borrowed". As the saying goes, "there is borrowing to have," but the question here is when. Suppose the borrowed workers had just finished a task and returned, and later found that the task was still there, wouldn't it be to borrow again? This one goes. The boss is sure to die of a big head.
Reasonable strategy: since borrowed. Let's borrow more for a while. Until "a certain period" of time, found that no longer use these workers. will be able to return it.
Some time here is the meaning of KeepAliveTime, Timeunit is the measure of KeepAliveTime value.
Rejectedexecutionhandler
There is one other case. Even though he borrowed the workers from the boss, the task continued. Still busy just come, when the whole team just refused to accept.
The Rejectedexecutionhandler interface provides the opportunity for a custom method to reject the processing of a task. The 4 policy has been included by default in Threadpoolexecutor because the source code is easy to post directly.
① callerrunspolicy: The thread invokes the execute itself that performs the task. This strategy provides a simple feedback control mechanism that can slow down the submission of new tasks.
public void Rejectedexecution (Runnable R, Threadpoolexecutor e) { if (!e.isshutdown ()) { r.run (); } }
This strategy obviously doesn't want to give up running tasks. However, because no resources are available in the pool, it is run directly using the thread itself that invokes the execute.
② abortpolicy: Handler rejection will throw execution rejectedexecutionexception
public void Rejectedexecution (Runnable R, Threadpoolexecutor e) { throw new rejectedexecutionexception ();
Such a policy throws an exception directly, discarding the task.
③ discardpolicy: A task that cannot be run will be deleted
public void Rejectedexecution (Runnable R, Threadpoolexecutor e) { }
Such a strategy and abortpolicy almost the same, but also to discard the task, just he does not throw an exception.
④ Discardoldestpolicy: Assuming that the running program has not been closed, the task that is in the head of the work queue is deleted, and then the program is retried (assuming it fails again, repeat this process)
public void Rejectedexecution (Runnable R, Threadpoolexecutor e) { if (!e.isshutdown ()) { e.getqueue (). poll (); C2/>e.execute (R); } }
The strategy is slightly more complicated, and first drops the oldest task cached in the queue without the pool shutting down. And then try to perform the task again. This strategy requires proper care.
Imagine: Assuming that other threads are still executing, then the new task kicks off the old task, slows down the queue, and a task kicks off the oldest task in the queue.
Summary
KeepAliveTime are related to the types of maximumpoolsize and Blockingqueue. Suppose the blockingqueue is unbounded. Then Maximumpoolsize will never be triggered. The natural KeepAliveTime also has no meaning.
Conversely, if the core number is smaller, the bounded blockingqueue value is smaller. At the same time KeepAliveTime is very small. Assume that the task is frequent. Then the system will frequently apply for recycling threads.
5.Java Thread Pool Usage Demo sample
①newsinglethreadexecutor
Mythread.java
public class MyThread extends Thread {@Overridepublic void run () {System.out.println (Thread.CurrentThread (). GetName () + "is running.。。
");}}
Testsinglethreadexecutor.java
public class Testsinglethreadexecutor {public static void main (string[] args) {//Create a thread pool of reusable fixed threads executorservice pool = E Xecutors.newsinglethreadexecutor ();//Create an object that implements the Runnable interface thread T1 = new MyThread (); Thread t2 = new MyThread (); Thread t3 = new MyThread (); Thread T4 = new MyThread (); Thread T5 = new MyThread ();//place thread into pool run Pool.execute (T1);p ool.execute (T2);p Ool.execute (T3);p ool.execute (T4); Pool.execute (T5);//close thread pool Pool.shutdown ();}}
Output Result:
Pool-1-thread-1 is running ...Pool-1-thread-1 is running ... Pool-1-thread-1 is running ... Pool-1-thread-1 is running ... Pool-1-thread-1 is running ...
②newfixedthreadpool
Testfixedthreadpool.java
public class Testfixedthreadpool {public static void main (string[] args) {//Create a thread pool with a reusable fixed number of threads executorservice pool = execut Ors.newfixedthreadpool (5);//Create an object that implements the Runnable interface thread T1 = new MyThread (); Thread t2 = new MyThread (); Thread t3 = new MyThread (); Thread T4 = new MyThread (); Thread T5 = new MyThread ();//place thread into pool run Pool.execute (T1);p ool.execute (T2);p Ool.execute (T3);p ool.execute (T4); Pool.execute (T5);//close thread pool Pool.shutdown ();}}
Output Result:
Pool-1-thread-2 is running ... Pool-1-thread-4 is running ...Pool-1-thread-1 is running.
。。 Pool-1-thread-3 is running.
。。 Pool-1-thread-5 is running.
。。
③newcachedthreadpool
Testcachedthreadpool.java
public class Testcachedthreadpool {public static void main (string[] args) {Executorservice pool = Executors.newcachedthre Adpool ();//Create an object that implements the Runnable interface thread T1 = new MyThread (); Thread t2 = new MyThread (); Thread t3 = new MyThread (); Thread T4 = new MyThread (); Thread T5 = new MyThread ();//place thread into pool run Pool.execute (T1);p ool.execute (T2);p Ool.execute (T3);p ool.execute (T4); Pool.execute (T5);//close thread pool Pool.shutdown ();}}
Output Result:
Pool-1-thread-2 is running:。
Pool-1-thread-4 is running:
。
Pool-1-thread-5 is running ... Pool-1-thread-1 is running ... Pool-1-thread-3 is running:
。
④newscheduledthreadpool
Testscheduledthreadpoolexecutor.java
public class Testscheduledthreadpoolexecutor {public static void main (string[] args) {Scheduledthreadpoolexecutor exec = New Scheduledthreadpoolexecutor, Exec.scheduleatfixedrate (New MyThread (), 0, timeunit.milliseconds);}
Java thread pool