Java thread pool

Source: Internet
Author: User

I. The question arises

Network requests usually have two scenarios: the first, the request is not very frequent, and each connection will remain for a considerable period of time to read data or write data, and finally disconnected, such as file download, network streaming media. The second is frequent requests, but the connection is disconnected after a small amount of data is read/written.
Given the concurrency of the service, if each request comes in after the service starts a thread for it, the resources for the service can be wasteful, especially in the second case. If the number of concurrent threads is large, and each thread is executing a short task, then the frequent creation of threads can greatly reduce the efficiency of the system because it takes time to create threads and destroy threads frequently.
So is there a way to enable a thread to be reused, to perform a task, not to be destroyed, but to continue to perform other tasks?
This can be achieved through the thread pool in Java.

Two. The Threadpoolexecutor class in Java

The Java.uitl.concurrent.ThreadPoolExecutor class is the most core class in the thread pool, so if you want a thorough understanding of the thread pools in Java, you must first understand this class. Let's look at the specific implementation of the Threadpoolexecutor class source.

Four construction methods are provided in the Threadpoolexecutor class:

PublicClassThreadpoolexecutorExtendsAbstractexecutorservice {PublicThreadpoolexecutor (int Corepoolsize,int Maximumpoolsize,Long keepalivetime,timeunit Unit, blockingqueue<runnable> WorkQueue);PublicThreadpoolexecutor (int corepoolsize,int maximumpoolsize,long keepalivetime,timeunit unit, blockingqueue<runnable> Workqueue,threadfactory threadfactory); public threadpoolexecutor (int corepoolsize,int maximumpoolsize,long keepalivetime,timeunit unit , blockingqueue<runnable> Workqueue,rejectedexecutionhandler handler); public threadpoolexecutor (int corepoolsize,int maximumpoolsize,long Keepalivetime,timeunit Unit, blockingqueue<runnable> workqueue,threadfactory Threadfactory,rejectedexecutionhandler handler); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

As you can tell from the code above, Threadpoolexecutor inherits the Abstractexecutorservice class and provides four constructors, in fact, by observing the concrete implementation of each constructor's source code, It is found that the first three constructors are initialized by the fourth constructor that is called.

The following explains the meanings of each parameter in the constructor:

  • Corepoolsize: The size of the core pool, this parameter is very much related to the implementation principle of the thread pool described later. After the thread pool has been created, by default, there are no threads in the thread pools, instead of waiting for a task to be created to perform the task, unless the prestartallcorethreads () or Prestartcorethread () method is called. As you can see from the names of these 2 methods, the meaning of the pre-created thread is to create a corepoolsize thread or a thread before the task arrives. By default, after a thread pool has been created, the number of threads in the thread pools is 0, and when a task comes, a thread is created to perform the task, and when the number of threads in the thread pool reaches corepoolsize, the incoming task is placed in the cache queue;
  • Maximumpoolsize: Thread pool Maximum number of threads, this parameter is also a very important parameter, it represents the maximum number of threads in the thread pool can be created;
  • KeepAliveTime: Indicates the maximum length of time a thread will be terminated without a task executing. By default, KeepAliveTime only works if the number of threads in the thread pool is greater than corepoolsize, until the number of threads in the thread pool is not greater than corepoolsize, that is, when the number of threads in the thread pool is greater than corepoolsize. If a thread is idle for KeepAliveTime, it terminates until the number of threads in the thread pool does not exceed corepoolsize. However, if the Allowcorethreadtimeout (Boolean) method is called, the KeepAliveTime parameter also works when the number of threads in the thread pool is not greater than corepoolsize, until the number of threads in the thread pool is 0;
  • Unit: The time unit of the parameter KeepAliveTime, there are 7 kinds of values, there are 7 kinds of static properties in the Timeunit class: Timeunit.days; Days Timeunit.hours; Hour timeunit.minutes; Minutes
    Timeunit.seconds; Seconds timeunit.milliseconds; Milliseconds
    Timeunit.microseconds; Subtle timeunit.nanoseconds; Na-Sec
  • WorkQueue: A blocking queue that stores the tasks waiting to be executed, and the choice of this parameter is also important to have a significant impact on the running process of the thread pool, in general, where the blocking queue has the following options:
    Arrayblockingqueue; Linkedblockingqueue; Synchronousqueue;
    Arrayblockingqueue and Priorityblockingqueue use less, generally using linkedblockingqueue and synchronous. The thread pool's queuing policy is related to Blockingqueue.
  • Threadfactory: Thread factory, primarily used to create threads, Handler: represents the following four values for policies when processing a task is rejected:
    Threadpoolexecutor.abortpolicy: Discards the task and throws a rejectedexecutionexception exception.
    Threadpoolexecutor.discardpolicy: Also discards the task, but does not throw an exception.
    Threadpoolexecutor.discardoldestpolicy: Discards the first task in the queue and then tries to perform the task again (repeat this process)
    Threadpoolexecutor.callerrunspolicy: The task is handled by the calling thread

There are several very important methods in the Threadpoolexecutor class:

    • Execute ()
    • Submit ()
    • Shutdown ()
    • Shutdownnow ()

The Execute () method is actually the method declared in executor, which is implemented in Threadpoolexecutor, which is the core method of Threadpoolexecutor, which can be used to submit a task to the thread pool. To the thread pool to execute.
The Submit () method is a method declared in Executorservice, which has a specific implementation in Abstractexecutorservice and is not overridden in threadpoolexecutor. This method is also used to submit a task to the thread pool, but unlike the Execute () method, it can return the result of the task execution and see the implementation of the Submit () method, and it will actually be called the Execute () method. It only uses the future to get the results of the task execution.
Shutdown () and Shutdownnow () are used to close the thread pool, call the shutdown () method, do not terminate the thread pool immediately, but wait until all tasks in the task cache queue have been executed before terminating, but will no longer accept new tasks; Call Shutdownnow () method to immediately terminate the thread pool and attempt to break the task that is being performed, and empty the task cache queue to return tasks that have not yet been performed.
There are many other methods, such as Getqueue (), Getpoolsize (), Getactivecount (), Getcompletedtaskcount (), and other methods to get the properties associated with the thread pool, and interested friends can consult the API themselves.

Three. Relationship between Threadpoolexecutor, Abstractexecutorservice, Executorservice and executor

Abstractexecutorservice class Source

PublicAbstractClassAbstractexecutorserviceImplementsExecutorservice {Protected <T> runnablefuture<t>Newtaskfor (Runnable Runnable, T value) {};Protected <T> runnablefuture<t>Newtaskfor (callable<t> callable) {};Public future<?>Submit (Runnable Task) {};Public <T> future<t>Submit (Runnable task, T result) {};Public <T> future<t>Submit (callable<t> Task) {};Private <T> TDoinvokeany (collection<? extends callable<t>> tasks,Boolean timed,Long Nanos)Throws Interruptedexception, Executionexception, timeoutexception {};Public <T> TInvokeany (collection<? extends callable<t>> tasks)throws interruptedexception, executionexception {}; public <T> T invokeany (collection<? extends callable <T>> tasks, long timeout, timeunit unit) throws Interruptedexception, Executionexception, timeoutexception {}; public <T> list<future<t>> invokeAll ( collection<? Extends callable<t>> tasks) throws interruptedexception {}; public <T> list<future<t>> invokeall (Collection<? Extends callable<t>> tasks, long timeout, timeunit unit) throws interruptedexception {};}         
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

Executorservice class Source

PublicInterfaceExecutorserviceExtendsExecutor {void shutdown ();Boolean IsShutDown ();Boolean isterminated ();Boolean awaittermination (Long timeout, timeunit unit)Throws Interruptedexception; <T> future<t> Submit (callable<t> Task); <T> future<t> Submit (Runnable task, T result); Future<?> Submit (Runnable Task); <T> list<future<t>> InvokeAll (collection<? extends callable<t>> tasks)throws interruptedexception; <T> list<future<t>> invokeall (collection<? extends callable <T>> tasks, long timeout, timeunit unit) throws interruptedexception; <T> T Invokeany (collection& lt;? Extends callable<t>> tasks) throws Interruptedexception, executionexception; <T> T Invokeany ( collection<? Extends callable<t>> tasks, long timeout, timeunit unit) throws Interruptedexception, Executionexception, TimeoutException;}     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22

Executor class Source

Public interface Executor {/** * executesTheGiven commandAtSometime in the future. The command * May execute in a new thread, in a pooled thread, or in the calling * thread, at the discretion of the <tt>Executor</tt> implementation. * * @param command the runnable task * @throws rejectedexecutionexception if this task cannot be * a ccepted for execution. * @throws nullpointerexception if Command is null */void Execute (Runnable command);       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

Executor is a top-level interface in which only one method execute (Runnable) is declared, the return value is void, the argument is of type Runnable, and is literally understood to be used to perform the task passed in;
Then the Executorservice interface inherits the executor interface and declares some methods: Submit, InvokeAll, Invokeany and shutdown, etc.
Abstract class Abstractexecutorservice implements the Executorservice interface, which basically implements all the methods declared in Executorservice;
Then Threadpoolexecutor inherits the class Abstractexecutorservice.

Four. Drill down into thread pool 1. Thread pool Status

A volatile variable is defined in Threadpoolexecutor, and several static final variables are defined to represent each state of the thread pool:

volatile int runState;static final int RUNNING = 0;static final int SHUTDOWN = 1;static final int STOP = 2;static final int TERMINATED = 3;
    • 1
    • 2
    • 3
    • 4
    • 5

Runstate represents the state of the current thread pool, which is a volatile variable used to ensure the visibility of the threads;
The following static final variables represent several possible values for runstate.
When the thread pool is created, it is initially in the running state;
If the shutdown () method is called, then the thread pool is in the shutdown state, and the line pool is not able to accept the new task, and it waits for all tasks to complete;
If the Shutdownnow () method is called, the thread pool is in the stop state, and this time, the thread pools are unable to accept new tasks, and will attempt to terminate the task being performed;
When the thread pool is in the shutdown or stop state, and all worker threads have been destroyed, the task cache queue has been emptied or the execution finishes, the thread pool is set to the terminated state.

2. Thread initialization in a thread pool

By default, after the thread pool is created, there are no threads in the threads pools, and threads are not created until the task is committed.
In practice, if you need to create threads immediately after the thread pool is created, there are two ways to do this:
Prestartcorethread (): Initializes a core thread;
Prestartallcorethreads (): Initialize all core threads
Here are the implementations of these 2 methods:

public boolean prestartCoreThread() {    return addIfUnderCorePoolSize(null); //注意传进去的参数是null}public int prestartAllCoreThreads() { int n = 0; while (addIfUnderCorePoolSize(null))//注意传进去的参数是null ++n; return n;}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

Note that the parameter passed in is null, according to the analysis of the source code, if the argument passed in is null, then the last execution thread will block r = Workqueue.take () in the Gettask method, that is, wait for tasks in the task queue.

3. Task cache queue and queuing policy

In the previous we mentioned the task cache queue, Workqueue, which is used to hold tasks waiting to be executed.
The type of Workqueue is blockingqueue and can usually be taken in the following three types:
1) Synchronousqueue: Directly commits the policy, it does not save the submitted task, but instead creates a new thread directly to perform the newly-arrived task. It will submit the task directly to the thread without maintaining it. If there is no thread available to run the task immediately, attempting to join the task to the queue will fail, and a new thread will be constructed.
2) Linkedblockingqueue: A list-based FIFO queue, which defaults to Integer.max_value if this queue size is not specified when it is created;
3) Arrayblockingqueue: array-based FIFO queue, this queue must be created with size specified, JDK deprecated;

4. Task Rejection Policy

When the thread pool's task cache queue is full and the number of threads in the thread pools reaches maximumpoolsize, a task rejection policy is taken if there is a task coming, typically with the following four strategies:

    • Threadpoolexecutor.abortpolicy: Discards the task and throws
    • Rejectedexecutionexception exception.
    • Threadpoolexecutor.discardpolicy: Also discards the task, but does not throw an exception.
    • Threadpoolexecutor.discardoldestpolicy: Discards the first task in the queue and then tries to perform the task again (repeat this process)
    • Threadpoolexecutor.callerrunspolicy: The task is handled by the calling thread
5. Dynamic adjustment of thread pool capacity

Threadpoolexecutor provides a way to dynamically adjust the size of the thread pool capacity: Setcorepoolsize () and Setmaximumpoolsize (),
Setcorepoolsize: Setting the core pool size
Setmaximumpoolsize: Set the maximum number of threads the thread pool can create
When the above parameters grow from small to large, threadpoolexecutor threads are assigned, and it is possible to create new threads immediately to perform tasks.

Five. Using the example

Creating a thread pool can use Threadpoolexecutor executor = new Threadpoolexecutor (size, maxSize, 1, timeunit.days, queue); This new way of creating, To configure a thread pool is more complex, especially if the thread pool principle is not very clear, it is likely that the thread pool configured is not superior, so there are some static factories in the executors class that generate some common thread pools.

    The
    • newsinglethreadexecutor
      Creates a single thread pool. This thread pool has only one thread at work, which is equivalent to single-threaded serial execution of all tasks. If this unique thread ends because of an exception, a new thread will replace it. This thread pool guarantees that the order in which all tasks are executed is performed in the order in which the tasks are submitted.
    • Newfixedthreadpool
      Creates a fixed-size thread pool. Each time a task is committed, a thread is created until the thread reaches the maximum size of the threads pool. Once the maximum size of the thread pool is reached, the thread pool will be replenished with a new thread if it ends up executing an exception. The
      fixed-size thread pool uses an unrestricted list by default. Note that this can cause resource exhaustion issues, but will not occur as long as the thread is processing faster than the queue grows. The
    • newcachedthreadpool
      Creates a cacheable thread pool. If the size of the thread pool exceeds the thread required to process the task, then a partially idle (60 second non-performing task) thread is reclaimed, and when the number of tasks increases, the thread pool can intelligently add new threads to handle the task. This thread pool does not limit the size of the thread pool, and the thread pool size is entirely dependent on the maximum thread size that the operating system (or JVM) can create.
    • newscheduledthreadpool
      Creates a thread pool of unlimited size. This thread pool supports the need to schedule and periodically perform tasks.
//Executeors中的实现public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

In the JDK help documentation, there is a phrase: "It is strongly recommended that programmers use the more convenient executors factory method Executors.newcachedthreadpool () (without a boundary pool, which can be automated for automatic recovery), Executors.newfixedthreadpool (int) (fixed-size thread pool), Executors.newsinglethreadexecutor () (a single background thread), all of which have predefined settings for most usage scenarios. ”

PublicClass test4{PublicStaticvoidMain (string[] args) {Executorservice threadPool = Executors.newcachedthreadpool ();Forint i =0; i<100; i++) {Workerthread thread =New Workerthread (i+""); Threadpool.submit (thread); } threadpool.shutdown (); }}class Workerthread implements Runnable {Private String command;PublicWorkerthread (String s) {This.command=s; } @Overridepublic void run () {System.out.println (Thread.CurrentThread (). GetName () + "Start. Command = "+command"); ProcessCommand (); System. out.println (Thread.CurrentThread (). GetName () + "End."); private void processCommand () { Span class= "Hljs-keyword" >try {thread.sleep (1000);} catch (interruptedexception e) {e.printstacktrace ();}} @Override public String tostring () { return this.command;}       

Java thread pool

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.