当前位置:网站首页>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的程序,大于这个就可以
边栏推荐
猜你喜欢
随机推荐
【 Leetcode string, the string transform/hexadecimal conversion 】 HJ1. The length of the string last word HJ2. Calculation of a certain number of characters appear HJ30. String merging processing
矢量图的作用与工具
程序员开发效率神器汇总!
华为研究院19级研究员几年心得,终成趣谈网络协议文档,附大牛讲解
go——协程调度
SQL学习笔记——REGEXP运算符
c语言实现三子棋
How to use PHP to implement lexical analyzer and custom language
Alibaba "MySQL Growth Manual" Lite Edition
MySQL-3-密码破解
WWW'22 推荐系统论文之多任务与对比学习篇
祝蔡徐坤生日快乐!
mysql 自动添加创建时间、更新时间
ICML/ICLR'22 推荐系统论文梳理
SQL查询数据以及排序
太帅了!我用炫酷大屏展示爬虫数据!
【Untitled】
vim的高级用法配置
Qt | QWidget 的一些总结
中科驭数等单位牵头发布行业首部DPU评测方法技术白皮书









