标签:调度 基本 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