When a new task is submitted in method execute(Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.

当提交task时,如果当前线程数小于corePoolSize,那么不管当前已创建线程是否处于空闲状态,总会创建一个新线程来处理该task。

Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using setCorePoolSize and setMaximumPoolSize.

核心线程数和最大线程数都可以动态调整。

By default, even core threads are initially created and started only when new tasks arrive, but this can be overridden dynamically using method prestartCoreThread or prestartAllCoreThreads. You probably want to prestart threads if you construct the pool with a non-empty queue.

创建ThreadPoolExecutor时,默认情况下,只有当有任务提交时,才会创建核心线程。不过也可以通过prestartCoreThread和prestartAllCoreThreads提前创建线程。当构造ThreadPoolExecutor时,如果使用非空queue,这很有用。

If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.

如果当前线程数小于corePoolSize,会直接新增一个线程,而不是把任务加到queue中。

A pool that is no longer referenced in a program AND has no remaining threads will be shutdown automatically. If you would like to ensure that unreferenced pools are reclaimed even if users forget to call shutdown, then you must arrange that unused threads eventually die, by setting appropriate keep-alive times, using a lower bound of zero core threads and/or setting allowCoreThreadTimeOut(boolean).

如果ThreadPoolExecutor不再被引用并且其没有存活的线程,那么它可以自动关闭,如果有存活的线程,就不会关闭。如果希望线程最终可以关闭,可以设置keep-alive times,并且设置核心线程数为0或者设置allowCoreThreadTimeOut。

线程增加(a)时机:

1. 任务提交时,当前线程数小于corePoolSize

2. 任务提交时,当前线程数小于maximumPoolSize,且任务队列满

3. 任务提交时,ThreadPoolExecutor处于运行状态,任务添加到队列,随后ThreadPoolExecutor变为非运行状态,任务又未从队列移除成功,且当前没有线程存活,创建一个线程处理该任务

4. 任务提交时,ThreadPoolExecutor处于运行状态,任务添加到队列,但之前创建线程全部die,则创建一个线程处理任务

5. 当前线程运行的任务出现异常,线程死掉,创建新线程替换旧线程(线程没有任务(completedAbruptly=false)或死掉时(completedAbruptly=true)会调用processWorkerExit)

    private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);
} finally {
mainLock.unlock();
} tryTerminate(); int c = ctl.get();
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null, false); // a5
}
}

6. setCorePoolSize, prestartCoreThread, prestartAllCoreThreads, ensurePrestart被调用时

任务reject(r)时机:

1. 任务提交时,当前ThreadPoolExecutor不处于运行状态

2. 任务提交时,当前ThreadPoolExecutor处于运行状态,但队列满,且核心线程数达到maximumPoolSize

3. 任务提交时,ThreadPoolExecutor处于运行状态,任务添加到队列,随后ThreadPoolExecutor变为非运行状态,任务从队列移除成功

    public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) // a1
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command); // r2,r3
else if (workerCountOf(recheck) == 0)
addWorker(null, false); // a3,a4
}
else if (!addWorker(command, false)) // a2
reject(command); // r1
}

线程退出时机:

1. 当前线程运行的任务出现异常

2. ThreadPoolExecutor处于shutdown,且队列为空

3. ThreadPoolExecutor处于非运行态和非shutdown态

4. 没有任务时(比如,当前线程数在core和max之间,只有当队列为空时线程才会退出,否则会执行任务到没有任务时退出)

5. setCorePoolSize, allowCoreThreadTimeOut, setMaximumPoolSize, setKeepAliveTime, shutdownNow, shutdown

ThreadPoolExecutor 杂记的更多相关文章

  1. Android线程管理之ThreadPoolExecutor自定义线程池

    前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...

  2. [Erlang 0118] Erlang 杂记 V

       我在知乎回答问题不多,这个问题: "对你职业生涯帮助最大的习惯是什么?它是如何帮助你的?",我还是主动回答了一下.    做笔记 一开始笔记软件做的不好的时候就发邮件给自己, ...

  3. 并发包的线程池第一篇--ThreadPoolExecutor执行逻辑

    学习这个很长时间了一直没有去做个总结,现在大致总结一下并发包的线程池. 首先,任何代码都是解决问题的,线程池解决什么问题? 如果我们不用线程池,每次需要跑一个线程的时候自己new一个,会导致几个问题: ...

  4. ThreadPoolExecutor源码学习(1)-- 主要思路

    ThreadPoolExecutor是JDK自带的并发包对于线程池的实现,从JDK1.5开始,直至我所阅读的1.6与1.7的并发包代码,从代码注释上看,均出自Doug Lea之手,从代码上看JDK1. ...

  5. ThreadPoolExecutor源码学习(2)-- 在thrift中的应用

    thrift作为一个从底到上除去业务逻辑代码,可以生成多种语言客户端以及服务器代码,涵盖了网络,IO,进程,线程管理的框架,着实庞大,不过它层次清晰,4层每层解决不同的问题,可以按需取用,相当方便. ...

  6. Java 线程 — ThreadPoolExecutor

    线程池 线程池处理流程 核心线程池:创建新线程执行任务,需要获取全局锁 队列:将新来的任务加入队列 线程池:大于corePoolSize,并且队列已满,小于maxPoolSize,创建新的worker ...

  7. Ubuntu杂记——Ubuntu下用虚拟机共享上网

    由于最近把自己电脑环境换成了Ubuntu,但学校的网络是电信的闪讯,大学里用过的人都知道这货有多坑,而且没有Linux客户端,上网都是问题,怪不得国内用Linux的人那么少,特别是高校的学生(让我瞎逼 ...

  8. java 线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用。

    转载请声明出处谢谢!http://www.cnblogs.com/linguanh/ 这里主要使用Executors中的4种静态创建线程池实例方法中的 newFixedThreadPool()来举例讲 ...

  9. 【JUC】JDK1.8源码分析之ThreadPoolExecutor(一)

    一.前言 JUC这部分还有线程池这一块没有分析,需要抓紧时间分析,下面开始ThreadPoolExecutor,其是线程池的基础,分析完了这个类会简化之后的分析,线程池可以解决两个不同问题:由于减少了 ...

随机推荐

  1. lucene学习笔记(四)lucene分词详解

    分词器的核心类 Analyzer SimpleAnalyzer StopAnalyzer WhitespaceAnalyzer StandardAnalyzer TokenStream 分词器做好处理 ...

  2. windows本地代码上传github

    1.下载Git工具 https://www.git-scm.com/download/win 2.进到项目目录 cd /dir/dir/dir/file 3.初始化 git init 4.添加远程仓库 ...

  3. postgresql 修改配置生效方法

    对于配置服务器,,太多时候我们在Linux中做的操作是,配置*.conf文件,然后重启服务.而很多服务都具有reload功能,而但是具体到某个配置,有时候直接说出需不需要重启服务而使得配置生效,这并不 ...

  4. UDP实现一个简易的聊天室 (Unity&&C#完成)

    效果展示(尚未完善) UDP User Data Protocol 用户数据报协议 概述 UDP是不连接的数据报模式.即传输数据之前源端和终端不建立连接.使用尽最大努力交付原则,即不保证可靠交付. 数 ...

  5. 对象初始化的完整过程(C#)

    1.静态构造函数 在引入本文的主题之前,我们先来铺垫一下吧,看看静态构造函数的概念及用途. C#中允许创建无参数构造函数,该函数仅执行一次.它一般被用来初始化静态字段.CLR不能保证在某个特定时刻执行 ...

  6. Impala源码之资源管理与资源隔离

    本文由  网易云发布. 前言 Impala是一个MPP架构的查询系统,为了做到平台化服务,首先需要考虑就是如何做到资源隔离,多个产品之间尽可能小的甚至毫无影响.对于这种需求,最好的隔离方案无疑是物理机 ...

  7. https经过ngxin在web服务器收到http请求

    一. 问题描述: nginx代理nexus的时候页面不全,部分https地址自动转成http了,使用方案四解决的 浏览器输入https://www.mysite.com,后台通过request.get ...

  8. java—实现一个监听器HttpServletRequest的创建销毁、在线人数 (56)

    在JavaWeb中的监听器分类 在Javaweb中存在三个被监听对象: HttpServletRequest HttpSessoin ServletContext 监听者 被监听者 监听到事件对象 H ...

  9. [RHEL] 配置 LVM 卷

    [RHEL] 配置 LVM 卷 一.Introduction 基础预览 :LVM 认知与扩容操作 高端实战:Linux系统如何迁移至LVM磁盘 之前转过一篇文章 LVM分区在线扩容 ,其原因是我需要给 ...

  10. 把redhat源换成centos的,解决redhat未注册不能下载相关软件的问题

      修改 vim /etc/yum.repos.d/centos-base.repo如下,清华源地址为  https://mirrors.tuna.tsinghua.edu.cn/help/cento ...