Thread pool concept and usage

What is the thread pool?

Popular understanding is a container, which put the number of threads, you need to use when taken out of use, run out to put under the back waiting for the next use.

Internal thread pool maintains a job queue, remove the thread from the pool to perform the task queue.

Why use a thread pool?

1. You can submit tasks and enforce policies decoupling, facilitate unified management tasks execution policy, good maintenance, such as delayed execution, set the wait time, overtime and other automatic failure.

2. improve performance, use the thread to perform tasks that have been created, reducing the overhead of creating and destroying threads.

3. restricted maximum number of concurrent threads to prevent endless threads cause poor performance and create a program to die.

4. The number of active threads, threads and the maximum number of configurable parameters, facilitate tuning.

How to create a thread pool?

Figure next example creates a core number of threads is 10, the maximum number of threads of 30 non-core thread length of 3 milliseconds when idle timeout thread pool, thread pool to submit three tasks.

1.png

Java thread pool ThreadPoolExecutor implements Executor interface provides several constructors as follows:

2.png

ThreadPoolExecutor individual parameters constructor meanings:

1. Core threads: int corePoolSize => the thread pool core maximum number of threads

New thread pool threads of time, if the current is less than the total number of threads corePoolSize, is the core of the new thread, if more than corePoolSize, the new non-core thread

Under default kernel threads in the thread pool it will always survive, even if the core thread what is not dry (idle).

If you specify ThreadPoolExecutor of allowCoreThreadTimeOut this property is true, then the core thread if you do not work (idle), then over a certain time (parameter determines the length of time below), will be destroyed out

Under normal circumstances you do not work, and I support you, because I always helpful to you, but sometimes special circumstances (such as I myself could not afford), then you do not work and you'll be blown away

2. The maximum number of threads the thread pool: int maximumPoolSize The maximum total number of threads in the thread pool. Total number of threads = + non-core number of threads core threads.

  1. 非核心线程闲置超时时长:long keepAliveTime

该线程池中非核心线程闲置超时时长

一个非核心线程,如果不干活(闲置状态)的时长超过这个参数所设定的时长,就会被销毁掉

如果设置allowCoreThreadTimeOut = true,则会作用于核心线程

4.时间单位:unit

指定keepAliveTime的时间单位,使用TimeUnit取值。

3.png

5.工作队列:workQueue

该线程池中的任务队列:维护着等待执行的Runnable对象

当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务

常用的workQueue类型:

  1. SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现 <线程数达到了maximumpoolsize而不能新建线程> 的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大
  2. LinkedBlockingQueue:这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize
  3. ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误
  4. DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务

ThreadPoolExecutor的策略

当一个任务被添加进线程池时:

  1. 线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
  2. 线程数量达到了corePools,则将任务移入队列等待
  3. 队列已满,新建线程(非核心线程)执行任务
  4. 队列已满,总线程数又达到了maximumPoolSize,就会由 RejectedExecutionHandler抛出异常

上面的构造参数太多太复杂,怕玩不转?

Concurrent包还提供了一套基于ThreadPoolExecutor的封装,使得使用者无需关注那么多配置细节,下图是Executors创建线程池的用法:

4.png

Executors创建的四种线程池:

1.可缓存线程池: CachedThreadPool

a.没有最大线程数限制,想创建多少就创建多少

b.有空闲线程就用空闲线程,没有就创建新线程

c.复用空闲线程能减少一部分重复创建销毁的开销

2. 定长线程池:FixedThreadPool

a.用来控制线程最大并发数。

b.如果没有空闲线程,剩下的任务会在队列等待有空闲线程执行。

3.支持定时和周期反复执行的定长线程池:ScheduledThreadPool

4.单线程的线程池:SingleThreadExecutor

线程池里只有一个线程,按照队列的出入规则来串行执行任务,例如先进先出。

线程池的大小设置多少合适?

线程池过大:大量线程竞争有限的cpu和内存资源,耗尽资源。

线程池过小:cpu利用率低,吞吐量低。

应当根据应用的特点来设计大小。

1.服务器的cpu多少?内存多大?任务是计算密集型还是IO密集型还是网络请求。

2.计算密集型的任务,在N个cpu的机器上大小为N或者N+1的线程池大小能实现最优使用率。

3. IO operations comprising IO intensive tasks or task, the thread would not have been executed, will wait IO response, provided the thread pool greater than N + 1, estimated by computing tasks waiting tasks monitoring tools and the ratio and then fine-tune a step by step, step by step, try to see what is the best performance.

Use the thread pool scene:

1, requires a lot of thread to complete the task and complete the task a relatively short time. WEB page request to the server to complete this task, use the thread pool technology is very appropriate. Because of the small single task, but a huge number of tasks, you can imagine the number of clicks a popular website. But for a long task, such as a Telnet connection request, the advantages of the thread pool is not obvious. Because Telnet session time most of the time than creating a thread.

2, the performance of demanding applications, such as requiring the server to respond quickly to customer requests.

3, a large number of requests accepted sudden, but does not cause the server application thus creating a large number of threads. Sudden large number of customer requests, in the absence of the thread pool situation, will have a large number of threads, although in theory the majority of the operating system the maximum number of threads is not a problem, a short time may produce a large number of threads to reach the memory limit, and the emergence of "OutOfMemory" mistake.

Do not use the thread pool scene:

1, if you need to make a task of a particular priority

2, if you have a potentially long-running (and therefore blocking other tasks) tasks

3, if the thread needs to be placed into a single-threaded unit (threads in the pool are in a multi-thread units)

Guess you like

Origin www.cnblogs.com/powerjiajun/p/11564182.html