Executors类的newFixedThreadPool, newCachedThreadPool, newScheduledThreadPool
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的更多相关文章
- java.util.concurrent.Executors类的常用方法介绍
Java 线程池 Executors提供了几种线程池实现? 5个,分别如下 1.newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收 ...
- Executors 类是什么?
Executors 为 Executor,ExecutorService,ScheduledExecutorService, ThreadFactory 和 Callable 类提供了一些工具方法. ...
- 【Java/Android性能优化1】Android性能调优
本文参考:http://www.trinea.cn/android/android-performance-demo/ 本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.La ...
- Android性能调优
本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等.一.性能瓶颈点整个页面主要由6个Page的ViewPager,每个Pag ...
- 【java线程池】
一.概述 1.线程池的优点 ①降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗: ②提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行: ③方便线程并发数的管控,线 ...
- java笔记--问题总结
1. 垃圾回收算法 标记-清除算法 标记-清除算法是最基本的算法,和他的名字一样,分为两个步骤,一个步骤是标记需要回收的对象.在标记完成后统一回收被标记的对象.这个算法两个问题.一个是效率问题,标记和 ...
- Android性能调优实例
本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等. 目前性能优化专题已完成以下部分: 性能优化总纲——性能问题及性能调优方 ...
- JUC——检视阅读
JUC--检视阅读 参考资料 JUC知识图参考 JUC框架学习顺序参考 J.U.C学习总结参考,简洁直观 易百并发编程,实践操作1,不推荐阅读,不及格 JUC文章,带例子讲解,可以学习2 Doug L ...
- 面试【JAVA基础】多线程
本次整理的内容如下: 1.进程与线程的区别 进程是一个可执行的程序,是系统资源分配的基本单位:线程是进程内相对独立的可执行单元,是操作系统进行任务调度的基本单位. 2.进程间的通信方式 2.1.操作系 ...
随机推荐
- Nodejs -- 使用koa2搭建数据爬虫
当前爬虫项目开发所需中间件: cheerio: 则能够对请求结果进行解析,解析方式和jquery的解析方式几乎完全相同 cheerio中文文档 开发参考node - cheerio模块 superag ...
- Java实现心跳机制
一.心跳机制简介 在分布式系统中,分布在不同主机上的节点需要检测其他节点的状态,如服务器节点需要检测从节点是否失效.为了检测对方节点的有效性,每隔固定时间就发送一个固定信息给对方,对方回复一个固定信息 ...
- Oracle RAC(Real Application Clusters)とは
ここからはOracle RAC(Real Application Clusters)の基本的な概念について述べていきたいと思います. 「RAC」の読み方は普通に「ラック」です. その前に.通常のデータ ...
- JS 获取浏览器的宽和高
网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWid ...
- 明码|2018年蓝桥杯B组题解析第二题-fishers
标题:明码 汉字的字形存在于字库中,即便在今天,16点阵的字库也仍然使用广泛. 16点阵的字库把每个汉字看成是16x16个像素信息.并把这些信息记录在字节中. 一个字节可以存储8位信息,用32个字节就 ...
- LA 3266 田忌赛马
https://vjudge.net/problem/UVALive-3266 题意: 田忌赛马,赢一局得200两银子,输一局赔200两银子,平局不赔不赚,问最多能赚多少银子. 思路: 先排序,然后比 ...
- 利用JSP中的过滤器解决中文乱码问题
首先我们创建过过滤器: package com.gbx; import java.io.IOException; import javax.servlet.Filter; import javax.s ...
- python 获取命令行输出结果
status, output = commands.getstatusoutput("sudo rm -rf a.txt") if(not status): print(" ...
- Could NOT find SDL (missing: SDL_LIBRARY SDL_INCLUDE_DIR)
sudo apt-get install libsdl-dev或 sudo apt-get install libsdl1.2-dev
- 编写 R Markdown 文档
数据分析师的工作不仅是将数据放入模型并得出一些结论.通常需要完成从数据收集.数据清理.可视化.建模再到最后编写报告或制作演示文稿的完整工作流程.在前面几章中,我们从不同方面深入学习 R 编程语言,从各 ...