java线程池总结(ThreadPoolExecutor与Executors特性及使用)
Posted 小艾路西里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java线程池总结(ThreadPoolExecutor与Executors特性及使用)相关的知识,希望对你有一定的参考价值。
1. 线程池简介
线程池是指预先创建好一定数量的线程对象,存入缓冲池中,需要用的时候直接从缓冲池中取出,线程结束之后会再回到缓冲池中
线程池在java中用ThreadPoolExecutor实现
线程池的优点
① 提高线程的利用率
② 提高响应速度
③ 便于统一管理线程对象
④ 可以控制最大的并发数
2. 线程池的使用
(1) 使用原生的ThreadPoolExecutor
① ThreadPoolExecutor7个参数的作用
corePoolSize:核心池的大小
maximumPoolSize:线程池的最大容量
:当核心池大小不够用时再加上拓展出的数量
keepAliveTime:线程存活时间
:在没有任务可执行的情况下(就绪队列也为空)备份线程存活的时)(必须是线程池中的数量大于 corePoolSize,才会生效,也就是拓展出的线程的存活时间)
TimeUnit:存活时间单位
BlockingQueue:等待队列,存储等待执行的任务
ThreadFactory:线程工厂,用来创建线程对象
RejectedExecutionHandler:拒绝策略
:当线程池达到最大容量后,拒绝提取线程的操作
4种等待队列
阻塞队列是用来存储等待执行的任务
1. ArrayBlockingQueue:基于数组的先进先出队列,创建时必须指定大小
2. LinkedBlockingQueue:基于链表的先进先出队列,创建时可以不指定大小,默认值时 Integer.MAX_VALUE
3. SynchronousQueue:它不会保持提交的任务,而是直接新建一个线程来执行新来的任务
4. PriorityBlockingQueue:具有优先级的阻塞队列
4种拒绝策略
1. AbortPolicy:直接抛出异常
2. DiscardPolicy:放弃任务,不抛出异常(多出来的线程默默丢弃)
3. DiscardOldestPolicy:尝试与等待队列中最前面的任务去争夺,不抛出异常
4. CallerRunsPolicy:谁调用谁处理(比如main方法调用线程池,则将多出来的线程交给main线程去完成任务)
② ThreadPoolExecutor的使用
public class Test {
public static void main(String[] args) {
Executor executorService = null;
try {
executorService = new ThreadPoolExecutor(
5, // 核心池容量
7, // 最大容量
1, // 存活时间
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<>(2), // 等待队列,这里设置的容量为2
Executors.defaultThreadFactory(), // 线程创建工厂,这里使用的是Executors工具类的默认线程工厂
new ThreadPoolExecutor.AbortPolicy() // 处理异常的方式,这里采用抛出异常
);
System.out.println("===");
for (int i = 0; i < 10; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"执行ing");
});
}
} catch (Exception e) {
System.out.println("超出了最大容量");
e.printStackTrace();
}
}
}
(2) 使用Executors 工具类
Executor接口的3种实现
① newSingleThreadExecutor();
// 单一线程池
② newFixedThreadPool(int nThreads);
// 固定数量线程池
③ newCachedThreadPool();
// 缓存线程池,数量随机,由电脑配置决定
从下列源码中可以看出,这3种线程池都是实例化的ThreadPoolExecutor,只是参数不同
NewSingleThreadExecutor
NewFixedThreadPool(int nThreads)
NewCachedThreadPool()
① NewSingleThreadExecutor()的使用
public class Test {
public static void main(String[] args) {
Executor executorService = Executors.newSingleThreadExecutor(); // 单一线程池
for (int i = 0; i < 10; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"执行ing");
});
}
}
}
同一个线程完成任务
② NewFixedThreadExecutor()的使用
Executor executorService = Executors.newFixedThreadPool(5); // 固定数量线程池 创建5个
for (int i = 0; i < 10; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"执行ing");
});
}
多个线程(这里是5个)完成任务
③ NewCachedThreadExecutor()的使用
ExecutorService executorService = Executors.newCachedThreadPool(); // 缓存线程池
for (int i = 0; i < 10; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"执行ing");
});
}
可见也是多个线程去执行任务
以上是关于java线程池总结(ThreadPoolExecutor与Executors特性及使用)的主要内容,如果未能解决你的问题,请参考以下文章