当前位置:网站首页>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的程序,大于这个就可以
边栏推荐
- 动态权重之多任务不平衡论文 (二) MetaBalance
- 5000mAh大电池!华为全新鸿蒙手机今晚亮相:更流畅更安全
- A status code, and access baidu process
- 性能测试详解(理论篇)
- Based on mobileNet dog breed classification (migration)
- BSC链智能合约模式系统开发功能逻辑分析
- esp32之arduino配置下载提速
- Win 10、Win 11 安装 MuJoCo 及 mujoco-py 教程
- Qt | 关于对象树和元对象的相关问题
- Alibaba "MySQL Growth Manual" Lite Edition
猜你喜欢
随机推荐
TMS320C6678开发板( DSP+Zynq )RTOS综合功能案例,嵌入式必看!
SQL查询数据之多表(关联)查询
vim的高级用法配置
2022 VMware下载安装教程
IPtables and binlog
虚拟现实处理器(SXR2130P)ISO7640FMDW(数字隔离器)说明
Go-4-在vim中无法跳转到源代码
【学习笔记之菜Dog学C】自定义类型详解(结构体+枚举+联合)
多线程------实际篇
线程安全问题以及其解决方法
Qt | 关于如何使用事件过滤器 eventFilter
es6 循环,并终止循环
系统存储的基本管理--挂载,分区,用户配额
暴力破解美团最新JVM面试题:无限执行
动态权重之多任务不平衡论文 (一)
不平衡之钥: 重采样法何其多
A status code, and access baidu process
看我如何用多线程,帮助运营小姐姐解决数据校对系统变慢!
CNN flower classification
PAT Class A 1145 Hash - Average Lookup Time