当前位置:网站首页>06-线程池(3大方法、7大参数,4种拒绝策略)
06-线程池(3大方法、7大参数,4种拒绝策略)
2022-08-02 15:06:00 【念奴娇6】
池化技术
程序运行的本质:占用系统的资源==》优化资源的使用==池化技术:提前准备好资源,如果需要使用,则到池里用,用完后释放返回给池里以备下次或其他线程使用。
线程池、连接池、内存池、对象池、创建销毁都非常的浪费资源。
优点
- 降低资源的消耗
- 提高响应的速度
- 方便管理
- 线程的复用,可以控制最大并发数,管理线程
三大方法
1单个线程池
新建单个线程池
/** * @author * @Date 2022/7/26 * @apiNote */
public class TApi {
public static void main(String[] args) {
ExecutorService singlePool=Executors.newSingleThreadExecutor();
try {
for (int i = 0; i < 100; i++) {
singlePool.execute(()->{
//代替new Thread.start(),利用线程池执行线程
System.out.println(Thread.currentThread().getName()+"OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
singlePool.shutdown();//关闭线程池
}
}
}
结果:
无论多少个线程处理,都在同一个线程池里面执行。
2固定线程池
新建固定个数的线程池
/** * @author * @Date 2022/7/26 * @apiNote */
public class TApi {
public static void main(String[] args) {
//新建5个线程池
ExecutorService fixedPool=Executors.newFixedThreadPool(5);
try {
for (int i = 0; i < 100; i++) {
fixedPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
fixedPool.shutdown();//关闭线程池
}
}
}
结果:
无论多少个线程执行,都在5个线程池当中。
3灵活线程池
根据系统CPU大小,灵活创建线程池,CPU越好,创建线程池越多。
/** * @author * @Date 2022/7/26 * @apiNote */
public class TApi {
public static void main(String[] args) {
ExecutorService cachedPool=Executors.newCachedThreadPool();
try {
for (int i = 0; i < 100; i++) {
cachedPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
cachedPool.shutdown();//关闭线程池
}
}
}
结果:
我的电脑当前可以创建最多线程池30个。
7大参数
源码:
//单个线程池源码
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
//固定线程池源码
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
//灵活线程池源码
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
//三个线程池的本质都是ThreadPoolExecutor
以下为ThreadPoolExecutor源码
public ThreadPoolExecutor(int corePoolSize,//核心线程大小
int maximumPoolSize,//最大核心线程池大小
long keepAliveTime,//超时了没有人调用就会释放
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂,创建线程的
RejectedExecutionHandler handler//拒绝策略) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
线程池不允许使用Executor去创建,而是通过ThreadPoolExecutor的方式,这样是为了让我们更好的了解线程池的运行规则,规避资源耗尽的风险。
Executor直接使用弊端为:
- FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,导致OOM,
- CachedThreadPool和SceduledThreadPool:允许创建的线程数量为Integer.MAX_VALUE,可能会创建大量线程,导致OOM,
示例:
- 当有两个线程进行时:
/** * @author * @Date 2022/7/26 * @apiNote */
public class TApi {
public static void main(String[] args) {
ExecutorService threadPool =new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()//线程池满了,阻塞队列满了,进入后不再处理并抛出异常
);
try {
for (int i = 1; i <= 2; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
结果:
分析:当前两个核心线程池在处理
2.当有3个线程进行时
/** * @author * @Date 2022/7/26 * @apiNote */
public class TApi {
public static void main(String[] args) {
ExecutorService threadPool =new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()//线程池满了,阻塞队列满了,进入后不再处理并抛出异常
);
try {
for (int i = 1; i <= 3; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
结果:
分析:当前两个核心线程池在处理
3.四个线程:
两个核心线程池在处理
4.五个线程:
5.六个线程:
两个核心线程池外加一个线程池在处理。
6.八个线程
7.九个线程
当九个线程进行时,超过了设定最大线程池数量(5)+阻塞队列(3)个(8<9),触发拒绝策略abortPolicy,抛出异常。
四种拒绝策略
除去上面的AbortPolicy拒绝策略,以下还有三种:
1.CallerRunPolicy拒绝策略
含义:哪来的回哪去
结果:
由主线程发出的,超过设定数量,会返回给主线程。
2.DiscardPolicy拒绝策略
结果:
达到设定线程池的数量8后,队列满后,之后第九个线程会被废弃掉,不抛出异常。
3.DiscardOldestPolicy
结果:
达到设定的最大线程数量8,第九个会尝试和第一个竞争,竞争成功会占用第一个,竞争失败就会自动丢弃掉。也不会抛出异常
最大线程如何定义
- CPU密集型:服务器几核CPU,就定义最大线程池数,如12核CPU就定义线程池数最大数量为12,可以保证CPU利用效率最高
- IO密集型:判断程序中十分消耗IO的程序,大于这个就可以
边栏推荐
- esp32之arduino配置下载提速
- How to use PHP to implement lexical analyzer and custom language
- c语言实现排雷
- Why do I no longer recommend the enumeration strategy pattern?
- SQL查询数据之多表(关联)查询
- mysql 索引使用与优化
- Qt | 设置部件大小 sizeHint、minimumSizeHint、sizePolicy、stretch factor
- 美团面试:如何设计一个注册中心?
- 从特征交互到数据交互,浅谈深度点击率模型的新趋势
- QT基础第四天(4)qt事件机制:事件基础概念,常见事件机制,事件处理以及事件的重写
猜你喜欢
2022 Security Officer-A Certificate Exam Questions and Mock Exam
Apache management and web optimization
vim的高级用法配置
快速搞懂Seata分布式事务AT、TCC、SAGA、XA模式选型
esp32之arduino配置下载提速
管理软件开发 管理软件定制开发流程
How to check the WeChat applet server domain name and modify it
Getting Started with MySQL Syntax
【Untitled】
Typora永久使用,彻底解决This beta version of Typora is expired.
随机推荐
数据防泄漏产品该如何选择
中科驭数等单位牵头发布行业首部DPU评测方法技术白皮书
第十五天笔记
阿里面试败北:5种微服务注册中心如何选型?这几个维度告诉你
程序员开发效率神器汇总!
MySQL查询
Application software code signing certificate
MySQL 视图(详解)
统计二进制中1的个数,两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
Qt | 控件之 QCheckBox
Qt | Qt 的项目文件.pro 文件详解
23、wpf之布局(一)
MySQL 的几种碎片整理方案总结(解决delete大量数据后空间不释放的问题)
MySQL 行级锁(行锁、临键锁、间隙锁)
SQL查询数据之多表(关联)查询
已经2022下半年了,居然还在说链动2+1!
vim的高级用法配置
SQL实现将多行记录合并成一行
SIGIR'22 推荐系统论文之POI篇
第十四天笔记