码迷,mamicode.com
首页 > 编程语言 > 详细

线程池

时间:2019-05-10 15:06:46      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:调度   基本   on()   ant   dfa   rdp   hand   信息   shu   

一、基本架构

1、Executor
它是"执行者"接口,它是来执行任务的。准确的说,Executor提供了execute()接口来执行已提交的 Runnable 任务的对象。Executor存在的目的是提供一种将"任务提交"与"任务如何运行"分离开来的机制。
只有一个接口:void execute(Runnable command)
2、ExecutorService
ExecutorService继承于Executor。它是"执行者服务"接口,它是为"执行者接口Executor"服务而存在的;准确的话,ExecutorService提供了"将任务提交给执行者的接口(submit方法)","让执行者执行任务(invokeAll, invokeAny方法)"的接口等等。
3、AbstractExecutorService
是一个抽象类,它实现了ExecutorService接口,存在的目的是为ExecutorService中的函数接口提供了默认实现。
4、ThreadPoolExecutor
"线程池"。它继承于AbstractExecutorService抽象类。
5、Executors
静态工厂类。它通过静态工厂方法返回ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 等类的对象。

 

二、ThreadPoolExecutor
线程池的理解:存放一定数量线程的一个线程集合。线程池允许多个线程同时执行,允许同时运行的线程数量就是线程池的容量;当添加的到线程池中的线程超过它的容量时,会有一部分线程阻塞等待。
线程池会通过相应的调度策略和拒绝策略,对添加到线程池中的线程进行管理。

 1 // 阻塞队列。当线程池中的线程数超过它的容量的时候,线程会进入阻塞队列进行阻塞等待。
 2 private final BlockingQueue<Runnable> workQueue;
 3 // 互斥锁,通过mainLock实现了对线程池的互斥访问。
 4 private final ReentrantLock mainLock = new ReentrantLock();
 5 // 线程集合。一个Worker对应一个线程。线程池通过它实现了"允许多个线程同时运行"。
 6 private final HashSet<Worker> workers = new HashSet<Worker>();
 7 // “终止条件”,与“mainLock”绑定。
 8 private final Condition termination = mainLock.newCondition();
 9 // 线程池中线程数量曾经达到过的最大值。
10 private int largestPoolSize;
11 // 已完成任务数量
12 private long completedTaskCount;
13 // ThreadFactory对象,用于创建线程。
14 private volatile ThreadFactory threadFactory;
15 // 拒绝策略的处理句柄。"当某任务添加到线程池中,而线程池拒绝该任务时,线程池会通过handler进行相应的处理"
16 private volatile RejectedExecutionHandler handler;
17 // 当线程池处于空闲状态的时候,超过keepAliveTime时间之后,空闲的线程会被终止。
18 private volatile long keepAliveTime;
19 // 默认false:核心线程闲置的时候仍然保持存活。true:用keepAliveTime进行超时。
20 private volatile boolean allowCoreThreadTimeOut;
21 // 核心池大小
22 private volatile int corePoolSize;
23 // 最大池大小
24 private volatile int maximumPoolSize;

三、线程池的执行原理:
1)如果"线程池中任务数量" < "核心池大小"时,即线程池中少于corePoolSize个任务;此时就新建一个线程,并将该任务添加到线程中进行执行。
2)如果"线程池中任务数量" >= "核心池大小",并且"线程池是允许状态";此时,则将任务添加到阻塞队列中阻塞等待。在该情况下,会再次确认"线程池的状态",如果"第2次读到的线程池状态"和"第1次读到的线程池状态"不同,则从阻塞队列中删除该任务。
3)非以上两种情况。在这种情况下,尝试新建一个线程,并将该任务添加到线程中进行执行。如果执行失败,则通过reject()拒绝该任务。

 

四、线程池的5种状态:
ctl是一个AtomicInteger类型的原子对象。ctl记录了"线程池中的任务数量"和"线程池状态"2个信息。
ctl共包括32位。其中,高3位表示"线程池状态",低29位表示"线程池中的任务数量"。
RUNNING(111):能够接收和处理任务,线程池一旦被创建就处于RUNNING状态。
SHUTDOWN(000):不接收新任务,可处理已添加的任务。调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
STOP(001):不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
TIDYING(010):当所有的任务已终止,ctl记录的"任务数量"为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,
若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
TERMINATED(011):线程池彻底终止,就变成TERMINATED状态。线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

 

五、拒绝策略
线程池的拒绝策略,是指当任务添加到线程池中被拒绝,而采取的处理措施。
当任务添加到线程池中之所以被拒绝,可能是由于:第一,线程池异常关闭。第二,任务数量超过线程池的最大限制。
线程池共包括4种拒绝策略:
AbortPolicy(默认) -- 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常
CallerRunsPolicy -- 当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。
DiscardOldestPolicy -- 当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中
DiscardPolicy -- 当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。

 

线程池

标签:调度   基本   on()   ant   dfa   rdp   hand   信息   shu   

原文地址:https://www.cnblogs.com/raynnie/p/10844242.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!