Java thread pool Threadpoolexecutor

Source: Internet
Author: User
Tags sorts

Benefits of the thread pool

1. Reduce the consumption of resources

Reduce the consumption caused by thread creation and destruction by reusing created threads

2. Improve response speed

When a task arrives, the task can be executed immediately without waiting for the thread to be created

3. Increase the manageable type of thread

Threads are scarce resources that, if created indefinitely, not only consume system resources, but also reduce system stability, using a thread pool for uniform allocation, tuning, and monitoring.

Implementation principle

When a new task is submitted to the thread pool, the thread pool process is:

1). The thread pool determines whether threads in the core line constructor are performing tasks.

If not, a new worker thread is created to perform the task. If the thread constructor the core thread is performing the task, it goes to the next process.

2). The thread pool determines whether the work queue is full.

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). The thread pool determines whether threads in the thread pool are in a working state.

If not, a new worker thread is created to perform the task. If it is full, then give the saturation policy to handle the task.

Threadpoolexecutor executes the Execute () method:

1). If the currently running thread is less than corepoolsize, create a new thread to perform the task (note that performing this step requires acquiring a global lock)

2). If you are running a thread that is equal to or more than Corepoolsize, add the task to Blockingqueue.

3). If the task cannot be joined to Blockingqueue (the queue is full), a new thread is created to handle the task (note that this step requires a global lock).

4). If you create a new thread that will cause the currently running thread to exceed maximumpoolsize, the task is rejected and the Rejectedexecutionhandler.rejectedexecution () method is called.

Threadpoolexecutor takes the overall design approach to the above steps in order to avoid acquiring a global lock as much as possible when executing the Execute () method (that would be a severe, scalable bottleneck). After Threadpoolexecutor finishes preheating (the number of threads currently running is greater than or equal to corepoolsize), almost all of the Execute () method calls are performed step 2, and two step 2 does not need to acquire a global lock.

Source code Analysis. The above process analysis allows us to intuitively understand how the thread pool works, so let's look at the source code to see how it is implemented. The thread pool performs the task in the following ways:

1 public void Execute (Runnable command) {2 if         (command = = null) 3             throw new NullPointerException (); 4         //If thread Number is less than the number of basic threads, the thread is created and the current task is executed 5         if (poolsize >= corepoolsize | |!addifundercorepoolsize (command)) {6             // If the number of threads is greater than or equal to the number of basic threads or thread creation fails, the current task is placed in the work queue. 7             if (runstate = = RUNNING && workqueue.offer (command)) {8                 if (runstate! = RUNNING | | poolsize = 0) {9
   ensurequeuedtaskhandled (command)                 }11                 //If the thread pool is not running or the task cannot be placed in the queue and the current number of threads is less than the maximum allowable number of threads, create a thread to perform the task 12             } else if (command) {!addifundercorepoolsize                 //throws Rejectedexecutionexception exception                 reject (command );//is shutdown or saturated15             }17         }18     }

worker Threads . When the thread pool creates threads, the thread is encapsulated as a worker thread worker,worker the tasks in the work queue are executed indefinitely after the task is completed. We can see this from the worker's Run method:

1 public void Run () {2  3      try {4  5            Runnable task = firsttask; 6  7            firsttask = null; 8  9             W Hile (Task! = NULL | | (Task = Gettask ()) = null) {Ten                     runTask (Task);                     task = null;14             }16)       finally {              Rkerdone (this);       }22 23}

Creation of the thread pool

We can create a thread pool through threadpoolexecutor.

12 newThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, milliseconds,runnableTaskQueue, threadFactory,handler);


To create a thread pool, you need to enter a few parameters:

    • corepoolsize(basic size of the thread pool): When a task is submitted to the thread pool, the thread pool creates a thread to perform the task, even if other idle basic threads are able to perform new tasks, Wait until the number of tasks that need to be executed is greater than the thread pool base size. If the thread pool's Prestartallcorethreads method is called, the thread pool creates and starts all basic threads in advance.
    • runnabletaskqueue(Task queue): A blocking queue that is used to hold tasks waiting to be executed. You can select the following blocking queues.
    1. Arrayblockingqueue: is a bounded blocking queue based on the array structure, which sorts the elements in FIFO (first-out) principle.
    2. Linkedblockingqueue: A blocking queue based on a linked list structure, which sorts elements in FIFO (first-out), with throughput typically higher than arrayblockingqueue. The static Factory Method Executors.newfixedthreadpool () uses this queue.
    3. Synchronousqueue: A blocking queue that does not store elements. Each insert operation must wait for another thread to invoke the remove operation, or the insert operation will always be in a blocked state, with throughput typically higher than linkedblockingqueue, and the static factory method Executors.newcachedthreadpool Use this queue.
    4. Priorityblockingqueue: an infinite blocking queue with priority.
    • maximumpoolsize(maximum thread pool size): The maximum number of threads allowed to be created by a thread pool. If the queue is full and the number of threads that have been created is less than the maximum number of threads, the thread pool will then create new threads to perform the task. It is worth noting that if you use the unbounded task queue This parameter has little effect.
    • threadfactory: Used to set the factory for creating threads, you can set a more meaningful name for each thread that is created through the thread factory, and it is very helpful to debug and locate problems.

Rejectedexecutionhandler (Saturation policy): When the queue and thread pool are full, indicating that the thread pools are saturated, a policy must be taken to handle the new tasks that are submitted. This policy is abortpolicy by default, indicating that an exception is thrown when a new task cannot be processed. The following are the four strategies provided by JDK1.5. N AbortPolicy: Throws an exception directly.

    1. Callerrunspolicy: runs the task only with the caller's thread.
    2. Discardoldestpolicy: Discards the most recent task in the queue and executes the current task.
    3. Discardpolicy: not processed, discarded.
    4. It is also possible to implement the Rejectedexecutionhandler interface customization strategy According to the application scenario. Tasks such as logging or persistence that cannot be processed.
    • keepalivetime(thread activity hold time): When the worker thread of the thread pool is idle, the time to remain alive. So if the task is a lot, and each task executes a short time, you can adjust the time to increase the utilization of the thread.
    • timeunit(unit of thread activity hold time): Optional unit with day (days), hours (HOURS), minutes (MINUTES), milliseconds (MILLISECONDS), microseconds (microseconds, 1 per thousand ms) and nanoseconds (nanoseconds, 1 per thousand microseconds).

submit a task to the thread pool

We can use the task submitted by execute, but the Execute method does not return a value, so it is not possible to tell whether the task is successfully executed by the thread pool. The following code shows that the task entered by the Execute method is an instance of the Runnable class.

1 Threadspool.execute (new Runnable () {2 @Override 3  4 public void Run () {5  6//TODO auto-generated method stub 7  8} 9 10});

We can also use the Submit method to submit the task, it will return a future, then we can determine whether the task succeeds, through the future of the Get method to get the return value, the Get method will block until the task is completed, and use Get (long Timeout, Timeunit unit) method will be blocked for a period of time immediately after the return, it is possible that the task is not finished.

try {  Object s = future.get ();} catch (Interruptedexception e) {//Handle interrupt exception} catch (Executionexception e) {//handle cannot perform task exception } finally {//closes the thread pool Executor.shutdown ();}
Shutdown of the thread pool

We can turn the thread pool off by invoking the shutdown or Shutdownnow method of the thread pool, but they are implemented differently, and the shutdown principle is simply to set the thread pool's state to shutdown state and then break all threads that are not performing the task. The principle of shutdownnow is to traverse the worker threads in the thread pool and then call the thread's interrupt method one by one, so that a task that cannot respond to the interrupt may never be terminated. Shutdownnow first sets the status of the thread pool to stop, and then tries to stop all threads that are executing or pausing the task, and returns a list of waiting tasks to be performed.

The IsShutDown method returns true whenever one of the two closing methods is called. The call to the Isterminaed method returns True when all tasks have been closed to indicate that the thread pool was successfully closed. As to which method we should call to close the thread pool, it should be determined by the task attributes submitted to the thread pool, usually called shutdown to close the thread pool, and shutdownnow can be called if the task is not necessarily finished.

Reasonable configuration of thread pool

To properly configure the thread pool, you must first analyze the task characteristics, which can be analyzed from the following angles:

    1. Nature of tasks: CPU-intensive tasks, IO-intensive tasks, and hybrid tasks.
    2. Priority of tasks: high, Medium, and low.
    3. Task execution time: long, medium and short.
    4. task dependencies: Whether to rely on other system resources, such as database connections.

Tasks of a different nature can be handled separately by thread pools of different sizes. CPU-intensive tasks are configured with as few threads as possible, such as configuring thread pooling for ncpu+1 threads. IO-intensive tasks are configured as many threads as possible, such as 2*NCPU, due to the need to wait for IO operations and the thread is not always performing the task. Mixed-type tasks, if they can be split into a CPU-intensive task and an IO-intensive task, as long as the time difference between the two tasks is not too large, then the throughput rate after decomposition is higher than the serial execution throughput rate, if the two task execution time is too large, it is not necessary to decompose. We can get the number of CPUs for the current device through the Runtime.getruntime (). Availableprocessors () method.

Tasks with different priority levels can be handled using the priority queue Priorityblockingqueue. It allows high-priority tasks to be executed first, and it is important to note that low-priority tasks may never be executed if a task with a high priority is committed to the queue.

Tasks with different execution times can be handled by different sizes of thread pools, or priority queues can be used to perform tasks that have a short execution time.

A task that relies on the database connection pool, because the thread submits the SQL and waits for the database to return the results, and the longer the CPU idle time waits, the greater the number of threads should be, so that the CPU can be better utilized.

It is recommended to use bounded queue , the bounded queue can increase the stability and early warning ability of the system, can be set to a larger point, such as thousands of. One time the queue and thread pool of the background task thread pool used by our group were full, and threw out the exception of the task, and by finding out that there was a problem with the database, the execution of SQL became very slow, because the tasks of the background task line constructor all needed to query and insert data into the database. So the work thread that causes the line constructor all blocks, the task backlog is constructor online. If we were to set up the unbounded queue, the thread pool would have more and more queues, potentially filling up the memory, making the whole system unusable, not just a background task. Of course all our system tasks are deployed with separate servers, and we use thread pools of different sizes to run different types of tasks, but this problem can also affect other tasks.

Monitoring of the thread pool

monitored by the parameters provided by the thread pool . Line constructor Some properties can be used when monitoring the thread pool

    • Taskcount: The number of tasks that the thread pool needs to perform.
    • Completedtaskcount: The number of tasks that the thread pool has completed during the run. Less than or equal to Taskcount.
    • Largestpoolsize: The maximum number of threads that the thread pool has ever created. This data lets you know if the thread pool is full. Equal to the maximum size of the thread pool means that the thread pool was once full.
    • Getpoolsize: The number of threads in the thread pool. If the thread pool is not destroyed, the threads in the pool will not be destroyed automatically, so this size only increases.
    • Getactivecount: Gets the number of active threads.

Monitor by extending the thread pool . By inheriting the thread pool and overriding the Beforeexecute,afterexecute and terminated methods of the thread pool, we can do something before the task executes and before the thread pool shuts down. such as the average execution time of the monitoring task, the maximum execution time and the minimum execution time. These several methods of online constructor are empty methods. Such as:

<b>protected</b> <b>void</b> BeforeExecute (Thread T, Runnable r) {}
    • <<java concurrent Programming Combat >>.
    • JDK1.6 source code.

More information:

Java thread pool Threadpoolexecutor

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: 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.