Java Thread Pool

Source: Internet
Author: User
Document directory
  • Role of Thread Pool
  • Why thread pool?
  • Principle of Thread Pool
  • Java Thread Pool
  • ThreadPoolExecutor
  • Executors
Role of Thread Pool

The thread pool is used to limit the number of execution threads in the system.

Depending on the system environment, you can automatically or manually set the number of threads to achieve the best running effect. If there are fewer threads, system resources will be wasted. If there are more threads, the system will be congested and inefficient. Use the thread pool to control the number of threads so that other threads can wait in queue. After a task is executed, the task starts from the top of the queue. If no task is waiting for a process in the queue, the thread in the thread pool is waiting.

Why thread pool?

Reduces the number of times threads are created and destroyed. Each worker thread can be reused to execute multiple tasks. You can also adjust the number of worker threads in the thread pool according to the system's capacity to prevent servers from getting tired due to excessive memory consumption (each thread requires about 1 MB of memory, the more threads open, the larger the memory consumed, and the machine crashes ).

Principle of Thread Pool

In fact, the thread pool principle is very simple. It is similar to the buffer concept in the operating system. The process is as follows: Start a number of threads and make these threads sleep, when the client has a new request, it will wake up a sleep thread in the thread pool and let it process the request from the client. After processing the request, the thread is sleeping again.

Java Thread Pool

The main content of java thread pool is as follows:
Interfaces: Executor, ExecutorService, ScheduledExecutorService, and CompletionService
Class: Executors, AbstractExecutorService, ThreadPoolExecutor, ScheduledThreadPoolExecutor, and ExecutorCompletionService

This section only introduces two important classes: Executors and ThreadPoolExecutor.

ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,                          int maximumPoolSize,                          long keepAliveTime,                          TimeUnit unit,                          BlockingQueue<Runnable> workQueue,                          ThreadFactory threadFactory,                          RejectedExecutionHandler handler)

Parameters:

● CorePoolSize-Number of threads stored in the pool, including Idle threads.
● MaximumPoolSize-Maximum number of threads allowed in the pool.
● KeepAliveTime-when the number of threads exceeds the core, this is the maximum time for Idle threads to wait for new tasks before termination.
● Unit-keepAliveTime parameter time unit.
● WorkQueue-the queue used to keep the task before execution. This queue only keeps Runnable tasks submitted by the execute method.
● ThreadFactory-the factory used by the execution program to create a new thread.
● Handler-the processing program used to block execution because it exceeds the thread range and queue capacity.

Throw:

● IllegalArgumentException-If corePoolSize or keepAliveTime is less than 0, maximumPoolSize is less than or equal to 0, or corePoolSize is greater than maximumPoolSize.
● NullPointerException-If workQueue, threadFactory, or handler is null.
● The optional parameters of unit are several static attributes in java. util. concurrent. TimeUnit: NANOSECONDS, MICROSECONDS, MILLISECONDS, and SECONDS.
● WorkQueue: java. util. concurrent. ArrayBlockingQueue
● Handler has four options:

1. ThreadPoolExecutor. AbortPolicy ()

Throw a java. util. concurrent. RejectedExecutionException

2. ThreadPoolExecutor. CallerRunsPolicy ()

Retry adding the current task and it will automatically call the execute () method again

3. ThreadPoolExecutor. DiscardOldestPolicy ()

Discard Old tasks

4. ThreadPoolExecutor. DiscardPolicy ()

Discard current task
A task is added to the thread pool using the execute (Runnable) method. A task is a Runnable object. The execution method of a task is the run () method of a Runnable object.
When a task is added to the thread pool by using the execute (Runnable) method, the following conditions are displayed:
1. If the number of threads in the thread pool is smaller than corePoolSize at this time, a new thread should be created to process the added tasks even if all threads in the thread pool are idle.
2. If the number in the thread pool is equal to corePoolSize, but the Buffer Queue workQueue is not full, the task is put into the buffer queue.
3. If the number in the thread pool is greater than corePoolSize, the Buffer Queue workQueue is full, and the number in the thread pool is smaller than maximumPoolSize, a new thread is created to process the added task.
4. If the number in the thread pool is greater than corePoolSize, the Buffer Queue workQueue is full, and the number in the thread pool is equal to maximumPoolSize, the handler policy is used to process the task. That is, the processing task priority is: Core Thread corePoolSize, task queue workQueue, and maximumPoolSize. If all three are full, handler is used to process the rejected task.
5. When the number of threads in the thread pool is greater than corePoolSize, if the idle time of a thread exceeds keepAliveTime, the thread will be terminated. In this way, the thread pool can dynamically adjust the number of threads in the pool.

Executors

Although ThreadPoolExecutor can be used to create a thread pool, the creation process is complex and cumbersome. It requires programmers to understand the meaning of each parameter and the creation process, executors can greatly simplify the process of creating a thread pool. Therefore, it is strongly recommended that programmers use the Executors factory method Executors. newCachedThreadPool () (unbounded thread pool, which can be automatically recycled), Executors. newFixedThreadPool (int) (fixed-size thread pool) and Executors. newSingleThreadExecutor () (a single background thread), which are predefined for most use cases. Otherwise, use the following instructions when manually configuring and adjusting the class:

Core and maximum pool size

ThreadPoolExecutor automatically adjusts the pool size based on the boundaries set by corePoolSize (see getCorePoolSize () and maximumPoolSize (see getMaximumPoolSize. When a new task is submitted in the execute (java. lang. Runnable) method, if the running thread is less than corePoolSize, a new thread is created to process the request, even if other auxiliary threads are idle. If the number of running threads is greater than corePoolSize and less than maximumPoolSize, a new thread is created only when the queue is full. If
If corePoolSize is the same as maximumPoolSize, a fixed thread pool is created. If you set maximumPoolSize to a basic unbounded value (such as Integer. MAX_VALUE), the pool is allowed to adapt to any number of concurrent tasks. In most cases, the core and maximum pool sizes are only set based on the constructor. However, you can also use setCorePoolSize (int) and setMaximumPoolSize (int) for dynamic changes.

Construct on demand

By default, you can use the prestartCoreThread () or prestartAllCoreThreads () method to dynamically override the Core Thread created and started only when the new task is required.
Create a thread
Use ThreadFactory to create a new thread. Otherwise, Executors. defaultThreadFactory () is used to create threads in the same ThreadGroup, and these threads have the same NORM_PRIORITY priority and non-daemon status. By providing different ThreadFactory, you can change the thread name, thread group, priority, and daemon status. If ThreadFactory fails to create a thread when return null from newThread, the execution program continues to run, but cannot execute any tasks.

Maintain activity time

If there are more threads in the pool than corePoolSize, these extra threads will be terminated when the idle time exceeds keepAliveTime (see getKeepAliveTime (java. util. concurrent. TimeUnit )). This provides a way to reduce resource consumption when the pool is inactive. If the pool becomes more active later, a new thread can be created. You can also use setKeepAliveTime (long, java. util. concurrent. TimeUnit) to dynamically change this parameter. Use Long. MAX_VALUE TimeUnit. NANOSECONDS
The value of can effectively disable idle threads from the previous termination status before closing.

Queuing

All BlockingQueue can be used to transfer and maintain submitted tasks. You can use this queue to interact with the pool size:
● If the number of running threads is less than corePoolSize, Executor always prefers to add new threads without queuing.
● If the running thread is equal to or greater than corePoolSize, Executor always prefers to add requests to the queue without adding new threads.
● If the request cannot be added to the queue, a new thread is created, unless the creation of this thread exceeds the maximumPoolSize. In this case, the task is denied.
There are three common queuing policies:
1. submit directly. The default Job Queue option is SynchronousQueue, which directly submits tasks to the thread without holding them. If there is no thread that can be used to run the task immediately, trying to add the task to the queue will fail, so a new thread will be constructed. This policy prevents locking when processing a collection of requests that may have internal dependencies. Direct submission usually requires unbounded maximumPoolSizes to avoid rejecting new tasks. This policy allows unbounded threads to grow when the command arrives continuously beyond the average number that the queue can handle.
2. Unbounded queues. The use of unbounded queues (for example, blockingqueue with no predefined capacity) will cause new tasks to be added to the queue when all corePoolSize threads are busy. In this way, the created thread will not exceed the corePoolSize. (Therefore, the value of maximumPoolSize is invalid .) When each task is completely independent from other tasks, that is, task execution does not affect each other, it is suitable to use unbounded queues. For example, in a Web Page Server. This kind of queuing can be used to handle transient bursts of requests. This policy allows unbounded threads to grow when the command arrives continuously beyond the average number that the queue can handle.
3. bounded queues. When a limited number of maximumPoolSizes are used, a bounded Queue (such as ArrayBlockingQueue) helps prevent resource depletion, but may be difficult to adjust and control. The queue size and the maximum pool size may need to be compromised: using large queues and small pools can minimize CPU usage, operating system resources, and context switching overhead, but may cause manual throughput reduction. If the tasks are frequently congested (for example, if they are I/O boundaries), the system may schedule a longer time than you permit for more threads. Using a small queue usually requires a large pool size, and the CPU usage is high, but it may encounter unacceptable scheduling overhead, which will also reduce the throughput.

Rejected task

When the Executor has been disabled and the Executor uses the finite boundary for maximum thread and work queue capacity, and is saturated, execute (java. lang. runnable. In both cases, the execute method calls the RejectedExecutionHandler's RejectedExecutionHandler. rejectedExecution (java. lang. Runnable, java. util. concurrent. ThreadPoolExecutor) method. The following provides four predefined handler policies:
1. In the default ThreadPoolExecutor. AbortPolicy, a running RejectedExecutionException will be thrown if the handler is rejected.
2. In threadpoolexecutor. callerrunspolicy, the thread calls the execute itself that runs the task. This policy provides a simple feedback control mechanism to speed down the submission of new tasks.
3. In threadpoolexecutor. discardpolicy, tasks that cannot be executed will be deleted.
4. In threadpoolexecutor. discardoldestpolicy, if the execution program is not closed, the task in the Job Queue header will be deleted, and then the execution program will be retried (if the execution fails again, the process will be repeated ).
Defining and using other types of rejectedexecutionhandler classes is also possible, but you need to be very careful when doing so, especially when the policy is only used for a specific capacity or queuing policy.

Hook method

This class provides the rewritable beforeexecute (Java. lang. thread, Java. lang. runnable) and afterexecute (Java. lang. runnable, Java. lang. throwable) method. These two methods are called before and after each task is executed. They can be used to manipulate the execution environment; for example, reinitializing threadlocal, collecting statistics, or adding log entries. In addition, you can override the terminated () method to execute all the special processing that needs to be completed after the executor is completely terminated.

If an exception is thrown by the hook or callback method, the Internal auxiliary thread will fail and terminate suddenly.

Queue Maintenance

The getqueue () method allows access to the work queue for monitoring and debugging purposes. It is strongly opposed to using this method for any other purpose. Remove (Java. Lang. runnable) and purge () methods can be used to help with storage collection when a large number of queued tasks are canceled.

 

Instance:

Import java. util. using list; import java. util. queue; import java. util. concurrent. arrayBlockingQueue; import java. util. concurrent. executors; import java. util. concurrent. rejectedExecutionHandler; import java. util. concurrent. scheduledExecutorService; import java. util. concurrent. scheduledFuture; import java. util. concurrent. threadPoolExecutor; import java. util. concurrent. timeUnit;/*** thread pool management * @ author LW * @ date 2011-2-12 */public class ThreadPoolManager {private static ThreadPoolManager tpm = new ThreadPoolManager (); // the minimum number of threads maintained by the thread pool private final static int CORE_POOL_SIZE = 3; // maximum number of threads maintained by the thread pool private final static int MAX_POOL_SIZE = 10; // the idle time allowed by the thread pool maintenance thread private final static int KEEP_ALIVE_TIME = 0; // The Buffer Queue size used by the thread pool private final static int WORK_QUEUE_SIZE = 10; // The Task Scheduling cycle private final stat Ic int TASK_QOS_PERIOD = 10; // task Buffer Queue private Queue <Runnable> taskQueue = new Queue list <Runnable> (); /** when the thread pool exceeds the boundary, add the task to the Buffer Queue */final RejectedExecutionHandler = new handler () {public void rejectedExecution (Runnable task, ThreadPoolExecutor executor) {taskQueue. offer (task) ;}};/** reload the tasks in the Buffer Queue to the thread pool */final Runnable accessBufferThread = new Runnable () {public void ru N () {if (hasMoreAcquire () {threadPool.exe cute (taskQueue. poll () ;}};/** create a scheduling thread pool */final ScheduledExecutorService schedors = Executors. newScheduledThreadPool (1);/** periodically execute tasks in the Buffer Queue through the scheduling thread */final ScheduledFuture <?> TaskHandler = schedler. scheduleAtFixedRate (accessBufferThread, 0, TASK_QOS_PERIOD, TimeUnit. MILLISECONDS);/** thread pool */final ThreadPoolExecutor threadPool = new ThreadPoolExecutor (CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit. SECONDS, new ArrayBlockingQueue <Runnable> (WORK_QUEUE_SIZE), this. handler);/** set the access modifier of the constructor to private and prohibit any instantiation. */Private ThreadPoolManager () {}/ ** method for creating a single thread pool instance */public static ThreadPoolManager newInstance () {return tpm ;} /** Message Queue Check Method */private boolean hasMoreAcquire () {return! TaskQueue. isEmpty ();}/** Add the task Method to the thread pool */public void addExecuteTask (Runnable task) {if (task! = Null) {threadPool.exe cute (task );}}}

 

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.