Java并发机制(7)--线程池ThreadPoolExecutor的使用
Java并发编程:线程池的使用
整理自:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3932921.html
1、什么是线程池,为什么要使用线程池:
1.1、线程池是线程的集合,里面的线程可以重复使用:java在java.util.concurrent下提供了一个Executor接口及其实现,用于创建管理线程池;线程池是指在初始化一个多线程应用时创建一个线程集合,再需要执行新的任务时,重复使用这些线程,而不是去创建新线程。
1.2、(1)缩短线程的创建和销毁时间,提高程序的性能;
(2)根据系统的承受能力,调整线程池中工作线程的数目,防止开销过大造成宕机。
1.3、常用的几种线程池:java doc不建议我么直接使用ThreadPoolExecutor创建线程池,而是使用Executors的静态方法创建;
(1):Executors.newCachedThreadPool(); 可缓存线程池,可根据需要创建新线程,终止超过60秒空闲的线程。
(2):Executors.newSingleThreadExecutor(); 只有一个单线程,串行执行所有任务。
(3):Executors.newFixedThreadPool(int):固定线程数线程池,达到固定数量后不新建也不消除。
2、Java中的ThreadPoolExecutor类
2.1、主要参数:corePoolSize:核心池的大小;maximumPoolSize:最大线程数;keepAliveTime:无任务时线程保持多久会终止;unit:KeepAliveTime的时间单位;workQueue:阻塞队列,存储等待执行的任务;threadFactory线程工厂用来创建线程;hander:拒绝处理任务时的策略; 2.2、继承关系:ThreadPoolExecutor继承自AbstractExecutorService实现了ExecutorService接口继承了Executor接口; 2.3、ThreadPoolExecutor中的主要方法:
execute():提交任务
submit():提交任务并返回结果Future;
shutdown()shutdownNow():关闭线程池;
2.4、线程池的状态:
Running(创建时运行)->ShutDown(调用shutdown)/Stop(调用ShutDownNow状态)->Terminated(上一状态,所有线程已销毁,缓存队列已经清空);
2.5、任务的执行:
【1】线程池有线程(<corePoolSize)空闲,来任务给空闲线程;
【2】CorePoolSize已满,尝试将任务进入等待队列,若不成功(workQueue已满)尝试新建线程去执行该任务;
【3】当前线程池数量达到maximumPoolSize,再来的任务采取拒绝策略(hander)处理任务;
【4】线程数量超过maximumPoolSize时,若空闲线程的空闲时间超过了keepAliveTime,线程被终止,知道线程数量不大于CorePoolSize;如果允许核心线程设置KeepAliveTime,那么核心线程空闲一定时间后也会被终止。
2.6、任务缓存队列workQueue及其排队策略:
workQueue用来存放等待执行的任务,类型为BlockingQueue<Runnable>通常取一下三种类型:
(1):ArrayBlockingQueue:基于数组的,先进先出,需要指名大小;
(2):LinkedBlockingQueue:基于链表的先进先出队列,默认大小Integer.MAX_VALUE
(3):synchronousQueue:不保存任务,直接开启新线程去执行任务。
2.7、任务拒绝策略:线程池任务缓存队列workQueue以满,且线程池内线程数目达到maximumPoolSize:
(1):ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
(2):ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
(3):ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
(4):ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
2.8、关闭:shutdown()等待所有任务结束,且不接受新任务;shutdownNow():立即关闭,尝试打断正在执行的任务,清空缓存队列。
2.9、线程池容量动态调整:setCorePoolSize()和setMaximumPoolSize();
3、:java中ThreadPoolExecutor的使用实例;
public class Test {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(5));
for(int i=0;i<15;i++){
MyTask myTask = new MyTask(i);
executor.execute(myTask);
System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());
}
executor.shutdown();
}
}
class MyTask implements Runnable {
private int taskNum;
public MyTask(int num) {
this.taskNum = num;
}
@Override
public void run() {
System.out.println("正在执行task "+taskNum);
try {
Thread.currentThread().sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task "+taskNum+"执行完毕");
}
}
结果:
正在执行task 0
线程池中线程数目:1,队列中等待执行的任务数目:0,已执行玩别的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:0,已执行玩别的任务数目:0
正在执行task 1
线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:0
正在执行task 2
线程池中线程数目:......
4、java.util.concurrent.ThreadPoolExecutor的继承关系

Java并发机制(7)--线程池ThreadPoolExecutor的使用的更多相关文章
- Java并发编程:线程池ThreadPoolExecutor
多线程的程序的确能发挥多核处理器的性能.虽然与进程相比,线程轻量化了很多,但是其创建和关闭同样需要花费时间.而且线程多了以后,也会抢占内存资源.如果不对线程加以管理的话,是一个非常大的隐患.而线程池的 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- (转)Java并发编程:线程池的使用
背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...
- Java并发编程:线程池的使用(转载)
转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- Java并发编程:线程池的使用(转载)
文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- [转]Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- 【转】Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- 13、Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- [转] 引用 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用
PS: Spring ThreadPoolTaskExecutor vs Java Executorservice cachedthreadpool 引用 [轰隆隆] 的 Java自带的线程池Thre ...
随机推荐
- C#值类型回收
函数调用在执行时,首先要在栈中为形参和局部变量分配存储空间,然后还要将实参的值复制给形参,接下来还要将函数的返回地址(该地址指明了函数执行结束后,程序应该回到哪里继续执行)放入栈中,最后才跳转到函数内 ...
- 【C#Task】TaskCreationOptions 枚举
根据 TaskCreationOptions 的不同,出现了三个分支 LongRunning:独立线程,和线程池无关 包含 PreferFairness时:preferLocal=false,进入全局 ...
- 二叉树的N中遍历方式和拓展应用
(一)创建二叉树,如下图所示,一个标准的二叉树是所有位于根节点的左侧的子节点都是比根节点小的,右侧则都是大于根节点的. public class BinaryNode { public int val ...
- Linux中 du (详解)、 df (详解)和 free(详解)以及它们的区别
转至:https://blog.csdn.net/qq_19167629/article/details/80915834?utm_medium=distribute.pc_relevant_t0.n ...
- Lua中如何实现类似gdb的断点调试--04优化钩子事件处理
在第一篇的01最小实现中,我们实现了一个断点调试的最小实现,在设置钩子函数时只加了line事件,显然这会对性能有很大的影响.而后来两篇02通用变量打印和03通用变量修改及调用栈回溯则是提供了一些辅助的 ...
- 微信小程序结合 tp实现秒杀
一:建表 1:用户表 2:订单表 3:收货地址 4:秒杀的商品表: 二: 微信后台方法 1 /** 2 * 秒杀接口 3 */ 4 public function seckill(Request $r ...
- laravel 7 H_ui ajax添加入库及前端jQuery Validate验证+后端验证
1:引入 H-ui 用户添加页面,并修改script对应的src,添加input框的name属性值 <!DOCTYPE HTML> <html> <head> &l ...
- ASP.NET Core框架探索之Authentication
今天我们来探索一下ASP.NET Core中关于权限认证,所谓权限认证,就是通过某些方式获取到用户的信息. 需要开启权限认证,我们首先需要在容器中注入认证服务,使用services.AddAuthen ...
- Centos8 Yum 安装Nginx指定版本
查看系统和EPEL的nginx版本 dnf info nginx 通过官方 yum 源安装nginx vi /etc/yum.repos.d/nginx.repo 列出所有版本 ...
- C/C++读取SEGY文件(三)
SEGY IO (IBM&PC) 本文档将介绍SEGY的读取与写入过程,其中包括IBM与PC两种数据格式的转换. 程序将调用IEEE2IBM.cpp文件完成IBM与PC格式的互相转换. 新建头 ...