线程池 ExecutorService

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池 ExecutorService相关的知识,希望对你有一定的参考价值。

参考技术A

并发,启动大量任务线程时,频繁的线程创建/销毁会造成浪费。(创建、运行、销毁都需要时间),采用线程池,线程复用技术,提高性能。

线程池实现类,ThreadPoolExecutor 类。

ThreadPoolExecutor 构造方法,实现不同类型线程池。

corePoolSize,核心线程数。
maximumPoolSize,允许的最大线程,超过报异常。
keepAliveTime,非核心线程活跃时间。
TimeUnit,时间度量。
BlockingQueue<Runnable>,任务队列,(无限、有限队列、栈)。
ThreadFactory,线程工厂。

不推荐直接使用 ThreadPoolExecutor 构造方法创建。

1,缓存

核心线程是0,最大线程 MAX_VALUE ,任务队列 SynchronousQueue 是一个管道,不存储,线程活跃时间60秒。
适用短期大量任务的场景。
某一时间段高并发任务,创建大量线程,任务结束后,线程变空闲,60s以内重用,处理新任务,空闲到达60s,销毁。

2,固定数量

核心线程、最大线程,自定义,LinkedBlockingQueue 任务队列,不设置空闲时间,无界队列。
适用长期任务场景。
任务队列无界,仅核心线程工作,keepAlieveTime 不需要设置。

3,单线程

核心线程、最大线程,数量1,LinkedBlockingQueue 任务队列,不设置空闲时间,无界队列。
适用单个任务顺序执行场景。
只有一个核心线程,新任务加入队列。

4,定时任务

ScheduledThreadPoolExecutor 实例,ThreadPoolExecutor 子类。
核心线程自定义,最大线程 MAX_VALUE,DelayedWorkQueue 任务队列,空闲时间10s。
适用指定有延迟的任务或周期性重复任务场景。
队列不是按照 submit 时间排序,以延时时间为优先级升序排序,延时时间短的,优先级高,先执行。

线程池 ThreadPoolExecutor 创建,将任务派发给线程池,execute() 方法,自动分配线程执行。

workerCountOf(c) 方法,判断工作线程数量,当 <核心线程数量,addWorker() 方法,创建线程,设标志位参数代表核心线程,任务将由新建核心线程处理。
当 >= 核心线程,isRunning(c) 方法,表示 c<0,offer()方法,将任务加入队列。
offer() 是非阻塞方法,如果队列已满,返回失败,此时,addWorker() 方法,创建线程,不设标志位参数代表非核心线程,任务将由新建的非核心线程处理。

新线程创建
如果工作线程 >CAPACITY 容量,或 >= 允许的最大值(创建核心线程 >= 核心线程数量),失败返回。

创建一个 Runnable 类型 Worker 对象,ThreadPoolExecutor 内部静态类,用户任务封装,newThread() 方法,创建新线程,将 Worker(this) 作为新线程任务主体。

将 Worker 任务加入 HashSet 集合,设置 workerAdded 标志,启动新线程( start方法),设置 workerStarted 启动标志,代表线程启动,执行 Worker 任务的 run() 方法,调用 runWorker() 方法(外部类方法)。

新线程执行 Worker 任务的 run() 方法,借助 Worker 开始为线程池工作,从 Worker 获取内部 Runnable(即 execute 派送的用户任务),并执行 run() 方法。
用户任务处理完成,线程不会马上结束,while 循环,继续 getTask() 方法,从任务队列中获取任务,该方法可能会导致阻塞,队列空则线程结束。

BlockingQueue 阻塞队列。

1,工作线程 wc > 核心线程
设置 timed 标志,队列采用阻塞等待,(poll + timeout方式),timeout 设置线程 keepAliveTime 时间 。
因此,即使队列没有任务,线程仍然存活,(任务进队列后可立即唤醒展开工作)。

2,工作线程 wc < 核心线程
(仅有核心线程),队列采用一直阻塞,( take 方式),队列是空时,线程一直阻塞,核心线程不会结束。

3,队列空,poll 超时
设置 timeOut 已超时标志,下次循环时,如果再发生工作线程 wc > 核心线程 ( timed 和 timedOut 标志并存),线程数量自减,退出 while 返回空,线程结束。

4,设置核心线程 allowCoreThreadTimeOut
不管工作线程 wc,采用 poll + timeout 方式,keepAliveTime 队列无任务,所有线程都会 timedOut 超时标志,下次循环自动结束。
即使 wc < 核心线程,线程也会结束退出,允许核心线程超时结束。

线程池本质,设置一定数量的线程集合,任务结束,但线程不结束,根据设定值,请求任务队列,继续任务,复用线程。

线程等待,利用任务队列的阻塞特性。阻塞任务队列,访问空队列时,线程等待,timeout 超时时间,实现线程 keepAliveTime 活动或一直存活。

任务队列
poll() 方法,取队列,非阻塞,poll + timeout,阻塞 timeout 时间。
take() 方法,取队列,阻塞等待。
put() 方法,存队列,阻塞等待,
offer() 方法,存队列,非阻塞,offer + timeout,阻塞 timeout 时间。

核心线程,在线程集合中,未具体标明,若 All 线程都完成任务,空闲,且队列空,在 getTask() 方法,根据超时时间,逐一唤醒,结束,剩下的数量 = 核心,它们即核心。

任重而道远

Java线程池 ExecutorService

java.util.concurrent包中的ExecutorService就是Java中对线程池的实现。

http://blog.csdn.net/suifeng3051/article/details/49443835

以上是关于线程池 ExecutorService的主要内容,如果未能解决你的问题,请参考以下文章

什么叫线程池?线程池如何使用?

多线程(六):线程池

多线程(六):线程池

十五、线程池(六)自动创建线程池的弊端

java 如何获得线程池中正在执行的线程数?

线程池参数与线程池调优