这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭。

先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法:

    public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException(); this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}

可以看到,尽管设定了corePoolSize,也就是Worker线程的数量,但是线程池开启的时候,默认是没有创建这些Worker线程的,但是ThreadPoolExecutor提供了prestartAllCoreThreads方法来开启所有的预设的Worker线程,以及prestartCoreThread尝试开启一个预设的Worker线程。

这里重点说说handler,也就是RejectedExecutionHandler,拒绝任务的处理类,ThreadPoolExecutor提供四种策略:

1. CallerRunsPolicy

该策略会在ThreadPoolExecutor没有关闭的情况,依旧运行任务

2. AbortPolicy

该策略会抛出一个RejectedExecutionException

3. DiscardPolicy

该策略直接忽略该任务,不会有任何动作

4. DiscardOldestPolicy

该策略会在ThreadPoolExecutor没有关闭的情况,丢弃下一个将要执行的任务,把该任务加入到执行队列。

接下来说说关闭,ThreadPoolExecutor提供了shutdown和shutdownNow两种方式,从字面上就能看出区别,后者会尝试结束正在运行的任务。

先来看shutdown:

    public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // ScheduledThreadPoolExecutor的回调方法
} finally {
mainLock.unlock();
}
tryTerminate();
}

再看shutdownNow:

    public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}

两个方法的代码非常相似,区别在于:

1. shutdownNow的状态设置为STOP,shutdown的状态是SHUTDOWN

2. shutdownNow会中断所有线程,也就是所有任务,而shutdown仅仅中断空闲线程,不会影响正在执行的任务。

3. shutdownNow会导出未执行的任务。

两个方法都用到的checkShutdownAccess方法主要是检查方法调用者是否有权限中断Worker线程。

advanceRunState方法用于设定线程的状态,如果状态值大于等于该状态值则会返回。关于状态值参看 《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分。

关于interruptIdleWorkers和interruptWorkers,在上一篇文章曾经说过Worker线程具备锁的功能,因此可以通过tryLock来判断Worker线程是否处于空闲状态,这是两个方法的区别所在。

这一部分写的有些凌乱,各位见谅。

《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分的更多相关文章

  1. 《java.util.concurrent 包源码阅读》 结束语

    <java.util.concurrent 包源码阅读>系列文章已经全部写完了.开始的几篇文章是根据自己的读书笔记整理出来的(当时只阅读了部分的源代码),后面的大部分都是一边读源代码,一边 ...

  2. 《java.util.concurrent 包源码阅读》04 ConcurrentMap

    Java集合框架中的Map类型的数据结构是非线程安全,在多线程环境中使用时需要手动进行线程同步.因此在java.util.concurrent包中提供了一个线程安全版本的Map类型数据结构:Concu ...

  3. 《java.util.concurrent 包源码阅读》02 关于java.util.concurrent.atomic包

    Aomic数据类型有四种类型:AomicBoolean, AomicInteger, AomicLong, 和AomicReferrence(针对Object的)以及它们的数组类型, 还有一个特殊的A ...

  4. 《java.util.concurrent 包源码阅读》17 信号量 Semaphore

    学过操作系统的朋友都知道信号量,在java.util.concurrent包中也有一个关于信号量的实现:Semaphore. 从代码实现的角度来说,信号量与锁很类似,可以看成是一个有限的共享锁,即只能 ...

  5. 《java.util.concurrent 包源码阅读》06 ArrayBlockingQueue

    对于BlockingQueue的具体实现,主要关注的有两点:线程安全的实现和阻塞操作的实现.所以分析ArrayBlockingQueue也是基于这两点. 对于线程安全来说,所有的添加元素的方法和拿走元 ...

  6. 《java.util.concurrent 包源码阅读》09 线程池系列之介绍篇

    concurrent包中Executor接口的主要类的关系图如下: Executor接口非常单一,就是执行一个Runnable的命令. public interface Executor { void ...

  7. 《java.util.concurrent 包源码阅读》24 Fork/Join框架之Work-Stealing

    仔细看了Doug Lea的那篇文章:A Java Fork/Join Framework 中关于Work-Stealing的部分,下面列出该算法的要点(基本是原文的翻译): 1. 每个Worker线程 ...

  8. 《java.util.concurrent 包源码阅读》25 Fork/Join框架之Fork与Work-Stealing(重写23,24)

    在写前面两篇文章23和24的时候自己有很多细节搞得不是很明白,这篇文章把Fork和Work-Stealing相关的源代码重新梳理一下. 首先来看一些线程池定义的成员变量: 关于scanGuard: v ...

  9. 《java.util.concurrent 包源码阅读》22 Fork/Join框架的初体验

    JDK7引入了Fork/Join框架,所谓Fork/Join框架,个人解释:Fork分解任务成独立的子任务,用多线程去执行这些子任务,Join合并子任务的结果.这样就能使用多线程的方式来执行一个任务. ...

随机推荐

  1. PPT的应用

    ppt是Office中一个制作演示文稿的一个办公软件使阐述过程简明而又清晰,轻松又丰富详实,从而有效表达自己以及与他人沟通,所创建的文件被称为电子演示文稿,其扩展名为.PPT.一个演示文稿由若干张电子 ...

  2. UVa225,Golygons

    刘儒家翻译的走出的图形可以自交,不知道大家是怎么理解的,反正我是认为这句话的意思是告诉我允许一个点访问多次 这样是WA的,n=15和n=16时多输出很多数据,应该是不允许自交,也就是不允许一个点访问多 ...

  3. Linux入门(10)——Ubuntu16.04使用pip3和pip安装numpy,scipy,matplotlib等第三方库

    安装Python3第三方库numpy,scipy,matplotlib: sudo apt install python3-pip pip3 install numpy pip3 install sc ...

  4. 【NOIP2015提高组】 Day2 T3 运输计划

    题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如: ...

  5. 217. Contains Duplicate (leetcode)

    Given an array of integers, find if the array contains any duplicates. Your function should return t ...

  6. Java基础-运算符(03)

    概念: 运算符:就是对于常量和变量进行操作的符号. 表达式:用运算符连接起来的符合java语法的式子,不同的运算符连接的表达式是不同类型的表达式. 运算符分类: 算数运算符(+  -  *  /  % ...

  7. MongoDB复制

    1. 什么是复制 (1)MongoDB复制是将数据同步在多个服务器的过程. (2)复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性. (3)复制还允 ...

  8. 学习UML --用例图

    用例图用于描述系统提供的系列功能.使用用例图的主要目的是帮助开发团队以一种可视化的方式理解系统的功能需求.用例图对系统的实现不做任何说明,仅仅是系统功能的描述. 用例图主要在需求分析阶段使用,用于描述 ...

  9. 利用Tkinter和matplotlib两种方式画饼状图

    当我们学习python的时候,总会用到一些常用的模块,接下来我就详细讲解下利用两种不同的方式画饼状图.首先利用[Tkinter]中的canvas画布来画饼状图: from tkinter import ...

  10. AngularJS学习篇(十六)

    AngularJS 表单 HTML 控件 以下 HTML input 元素被称为 HTML 控件: input 元素 select 元素 button 元素 textarea 元素 HTML 表单 H ...