Go Analysis and use of the Java thread pool

Source: Internet
Author: User
Tags sorts

1. Introduction

The rational use of the thread pool can bring three benefits.

First: reduce resource consumption. reduce the consumption caused by thread creation and destruction by reusing the threads that have been created.

Second: improve response speed. when a task arrives, the task can be executed immediately without waiting for the thread to be created.

Third: improve the manageability of threads. 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.

But to make reasonable use of the thread pool, it must be well-versed in its principles.

2. Use of the thread pool

Creation of the thread pool

We can create a thread pool through threadpoolexecutor .

New  Threadpoolexecutor (Corepoolsize, Maximumpoolsize, KeepAliveTime, Milliseconds,runnabletaskqueue, 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 line pool creates a thread to perform the task, and the thread is created even if other idle basic threads are able to perform new tasks, and is no longer created until the number of tasks that need to be executed is larger 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.
    • Arrayblockingqueue: is a bounded blocking queue based on the array structure, which sorts the elements in FIFO (first-out) principle.
    • 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.
    • 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.
    • Priorityblockingqueue: An infinite-blocking queue with a 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 created by the thread factory.
  • 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.
    • AbortPolicy: Throws an exception directly.
    • Callerrunspolicy: Runs the task only with the caller's thread.
    • Discardoldestpolicy: Discards the most recent task in the queue and executes the current task.
    • Discardpolicy: not processed, discarded.
    • 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 units have day (days), hours (HOURS), minutes (MINUTES), milliseconds (MILLISECONDS), microseconds (microseconds, 1 per thousand milliseconds), 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 determine whether the task was 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 .

Threadspool.execute (New Runnable () {            @Override public            void Run () {                //TODO auto-generated method stub            }        });

  

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, Using the Get (long timeout, Timeunit unit) method will block a period of time immediately after the return, it is possible that the task is not finished.

future<object> future = Executor.submit (Harreturnvaluetask); try {     Object s = future.get ();} catch ( Interruptedexception e) {    //handle Interrupt exception} catch (Executionexception e) {    //handle cannot perform task exception} finally {    //close thread pool 
   
    executor.shutdown ();}
   

  

Shutdown of the thread pool

We can close the thread pool by invoking the shutdown or Shutdownnow method of the thread pool, which is the principle

A task that iterates through the thread pool and then calls the thread's interrupt method one at a time, so that the failure to respond to an interrupted job may never be terminated.

But there are some differences, Shutdownnow first sets the state of the thread pool to stop, then tries to stop all the threads that are executing or pausing the task, and returns a list of waiting tasks, while shutdown only sets the state of the thread pool to shutdown state. It then interrupts all threads that are not performing the task.

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 shutdown to close the thread pool, you can call Shutdownnow if the task is not necessarily finished.

3. Thread Pool Analysis

Process Analysis: The main workflow of the thread pool is as follows:

As we can see, when a new task is submitted to the thread pool, the thread pool processes the following:

    1. First, the thread pool determines if the base thread pool is full? Not full, create a worker thread to perform the task. Full, then go to the next process.
    2. Next the thread pool determines if the task queue is full? is not full, the newly submitted task is stored in the work queue. Full, then go to the next process.
    3. the last thread pool determines if the entire thread pool is full? is not full, a new worker thread is created to perform the task, and the saturation policy is assigned to handle the task .

Source code Analysis .

The above process analysis gives us an intuitive understanding of how the thread pool works, so let's look at the source code to see how it's done. The thread pool performs the task in the following ways:

public void Execute (Runnable command) {    if (command = = null)       throw new NullPointerException ();    If the number of threads is less than the number of basic threads, create the thread and perform the current task if     (poolsize >= corepoolsize | |!addifundercorepoolsize (command)) {    // 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.        if (runstate = = RUNNING && workqueue.offer (command)) {            if (runstate! = RUNNING | | poolsize = 0)                      Ensu requeuedtaskhandled (command);        }    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, a thread is created to perform the task.        else if (!addifundermaximumpoolsize command)        //Throw Rejectedexecutionexception exception            reject (command); /is shutdown or saturated    }}

  

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:

public void Run () {     try {           Runnable task = Firsttask;           Firsttask = null;            while (task! = NULL | | (Task = Gettask ()) = null) {                    runTask (Task);                    task = null;            }      } finally {             workerdone (this);      

  

4. Reasonable configuration of the 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 small a thread as possible, such as configuring a thread pool for ncpu+1 threads.

IO-intensive tasks Configure as many threads as possible, such as 2*NCPU, because 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 caused the line constructor all blocked up,

Task backlog Online constructor.

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.

5. 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 are not automatically destroyed, so this size increases by no more than + 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:

protected void BeforeExecute (Thread T, Runnable r) {}

  

6. References
    • Java concurrent programming in combat.
    • JDK1.6 Source
Reproduced in chat concurrency (iii) analysis and use of--java thread pool

Go Analysis and use of the 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.