当前位置:网站首页>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的程序,大于这个就可以
边栏推荐
猜你喜欢
随机推荐
2022 Security Officer-A Certificate Exam Questions and Mock Exam
Qt | 控件之 QCheckBox
A status code, and access baidu process
Vest bag access process record
软件成分分析:华为云重磅发布开源软件治理服务
推荐系统相关顶会整理
Qt | 信号和槽的一些总结
中科驭数等单位牵头发布行业首部DPU评测方法技术白皮书
再见Attention:建模用户长期兴趣的新范式
SQL实现将多行记录合并成一行
系统存储的基本管理--挂载,分区,用户配额
MySQL-4-常规概念
Qt | 通过创建一个简单项目了解 Qt Creator
Based on mobileNet dog breed classification (migration)
23.支持向量机的使用
为什么我不再推荐枚举策略模式?
Go-5-简单介绍fmt库
Typora永久使用,彻底解决This beta version of Typora is expired.
数组的应用实例—三子棋
OneFlow源码解析:Op、Kernel与解释器