Executors 类对 ThreadPoolExecutor 的构造函数进行了封装,使用该类可方便地创建线程池。

1. newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
} // 对应的ThreadPoolExecutor设置如下:
this.corePoolSize = nThreads;
this.maximumPoolSize = nThreads;
this.workQueue = new LinkedBlockingQueue<Runnable>();
this.keepAliveTime = TimeUnit.MILLISECONDS.toNanos(0L);
this.threadFactory = Executors.defaultThreadFactory();
this.handler = defaultHandler;

2. newCachedThreadPool

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
} // 对应的ThreadPoolExecutor设置如下:
this.corePoolSize = 0;
this.maximumPoolSize = Integer.MAX_VALUE;
this.workQueue = new SynchronousQueue<Runnable>();
this.keepAliveTime = TimeUnit.SECONDS.toNanos(60L); //60秒
this.threadFactory = Executors.defaultThreadFactory();
this.handler = defaultHandler;

分析任务入队和出队,分别对应 ThreadPoolExecutor 类的 execute 方法和 getTask 方法:

public void execute(Runnable command) {
if (command == null)
throw new NullPointerException(); int c = ctl.get();
// corePoolSize=0,所以不会走这个分支
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 把任务放进队列。
// newCachedThreadPool使用的队列是SynchronousQueue,当没有线程因take阻塞时,offer返回false。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
//如果工作线程数为0,创建工作线程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 如果入队失败,则创建工作线程
else if (!addWorker(command, false))
reject(command);
}

cachedThreadPool 的一个特点是:工作线程执行完任务后,继续从工作队列获取任务(poll),等待60秒,超时则返回 null。task为 null时,工作线程就退出了 while 循环,也就是说这个线程要死了。

while (task != null || (task = getTask()) != null) {...}

3. newScheduledThreadPool

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
//对应ThreadPoolExecutor的设置
this.corePoolSize = corePoolSize;
this.maximumPoolSize = Integer.MAX_VALUE;
this.workQueue = new DelayedWorkQueue();
this.keepAliveTime = TimeUnit.NANOSECONDS.toNanos(0);
this.threadFactory = Executors.defaultThreadFactory();
this.handler = defaultHandler;

分析定时器延迟队列的 take 方法:DelayedWorkQueue 的底层是堆,访问堆顶的任务,如果任务的时间到了,则返回,否则等待直到时间到来。

// ScheduledThreadPoolExecutor.DelayedWorkQueue
public RunnableScheduledFuture take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture first = queue[0];
if (first == null)
available.await();
else {
long delay = first.getDelay(TimeUnit.NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
else if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
}

可以看出,3种线程池的主要区别是使用的队列不同。

4. DefaultThreadFactory

static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix; DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
} public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false); //设置为前台线程
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}

如果 Runnable 任务抛出了异常,线程池的工作线程还在吗?在的,线程会 terminate 掉,然后添加一个新的 Worker

Executors类的newFixedThreadPool, newCachedThreadPool, newScheduledThreadPool的更多相关文章

  1. java.util.concurrent.Executors类的常用方法介绍

    Java 线程池 Executors提供了几种线程池实现? 5个,分别如下 1.newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收 ...

  2. Executors 类是什么?

    Executors 为 Executor,ExecutorService,ScheduledExecutorService, ThreadFactory 和 Callable 类提供了一些工具方法. ...

  3. 【Java/Android性能优化1】Android性能调优

    本文参考:http://www.trinea.cn/android/android-performance-demo/ 本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.La ...

  4. Android性能调优

    本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等.一.性能瓶颈点整个页面主要由6个Page的ViewPager,每个Pag ...

  5. 【java线程池】

    一.概述 1.线程池的优点 ①降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗: ②提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行: ③方便线程并发数的管控,线 ...

  6. java笔记--问题总结

    1. 垃圾回收算法 标记-清除算法 标记-清除算法是最基本的算法,和他的名字一样,分为两个步骤,一个步骤是标记需要回收的对象.在标记完成后统一回收被标记的对象.这个算法两个问题.一个是效率问题,标记和 ...

  7. Android性能调优实例

    本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等. 目前性能优化专题已完成以下部分: 性能优化总纲——性能问题及性能调优方 ...

  8. JUC——检视阅读

    JUC--检视阅读 参考资料 JUC知识图参考 JUC框架学习顺序参考 J.U.C学习总结参考,简洁直观 易百并发编程,实践操作1,不推荐阅读,不及格 JUC文章,带例子讲解,可以学习2 Doug L ...

  9. 面试【JAVA基础】多线程

    本次整理的内容如下: 1.进程与线程的区别 进程是一个可执行的程序,是系统资源分配的基本单位:线程是进程内相对独立的可执行单元,是操作系统进行任务调度的基本单位. 2.进程间的通信方式 2.1.操作系 ...

随机推荐

  1. Android Socket 知识点汇总

    版权声明:这篇博客资料来源 https://blog.csdn.net/carson_ho/article/details/53366856 , 未经授权,严禁转发! 一.网络基础 1.1 计算机网络 ...

  2. 20145105 《Java程序设计》实验五总结

    实验五 JAVA网络编程 一.实验内容 用老师给的代码,实现服务器和客户端 和结对同学实现服务器与客户端的连接 客户端输入数据并加密,将密文发送给服务器,服务器接收密文并解密 二.实验步骤 用老师给的 ...

  3. Educational Codeforces Round 21 Problem D(Codeforces 808D)

    Vasya has an array a consisting of positive integer numbers. Vasya wants to divide this array into t ...

  4. bzoj 1010 玩具装箱toy -斜率优化

    P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具 ...

  5. python面向对象总结!

    面向对象 Object Oriented Programming 基本单元:对象把数据和功能封装在里边,能实现很好的复用性,灵活性和扩展性. 面向对象的两个基本概念:类和对象 面向对象的基本要素:属性 ...

  6. Python3基础 str lstrip 去掉字符串左边的空格

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  7. P3939 数颜色

    目录 题目 思路1(待修莫队) 思路2(vector+二分) 代码1 代码2 题目 P3939 数颜色 思路1(待修莫队) 哇,这不是莫队模板题吗 3e5,TLE45分 不行 我有信仰啊 pow(n, ...

  8. BZOJ 1044: [HAOI2008]木棍分割 DP 前缀和优化

    题目链接 咳咳咳,第一次没大看题解做DP 以前的我应该是这样的 哇咔咔,这tm咋做,不管了,先看个题解,再写代码 终于看懂了,卧槽咋写啊,算了还是抄吧 第一问类似于noip的那个跳房子,随便做 这里重 ...

  9. react 为元素添加自定义事件监听器

    https://zhenyong.github.io/react/tips/dom-event-listeners.html class MovieItem extends React.Compone ...

  10. org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement profile

    原创:转载请注明出处 1.异常情况 org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected ...