概述
文章目录
- 前言
- 一、构造函数
- 二、参数解释
- 三、案例分析
前言
在实际开发中,线程池的创建不能使用Exectors去创建线程池,而是采用最原始的ThreadPoolExecutor来创建线程池,这样可以让编写人员更加明确线程池的运行规则,避免不必要的错误。下面我们就来看看ThreadPoolExecutor的构造参数以及它们的作用。
一、构造函数
ThreadPoolExecutor一共有四种有参构造,下面只给出参数最全的构造函数
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
二、参数解释
- corePoolSize:即使空闲时仍保留在池中的线程数(核心线程数)
- maximumPoolSize:池中允许的最大线程数(核心线程数+救急线程数)
注:救急线程是在任务数大于核心线程数时创建的线程,用于救急,用完以后过指定时间自动销毁 - keepAliveTime:当线程数大于内核时,这是多余的空闲线程在终止前等待新任务的最大时间。
- unit:keepAliveTime参数的时间单位
- workQueue:用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务。
- threadFactory:执行程序创建新线程时使用的工厂
- handler:达到线程限制和队列容量时,执行的拒绝策略
三、案例分析
- 自定义Runnable实现类
class MyRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 构造函数
/*
默认开启1个线程,最大可开启3个线程,
当救急线程等待新任务超过1秒后没被使用就会销毁救急线程,
允许2个任务进入LinkedBlockingDeque阻塞队列等待,
用了Executors对象提供的默认线程创建工厂,
AbortPolicy表示拒绝任务的处理程序。
*/
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
1, 3,
1, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
-
相关介绍:
- LinkedBlockingDeque:是双向链表实现的双向并发阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除);并且,该阻塞队列是支持线程安全。
- AbortPolicy: 线程池的默认拒绝策略,即丢弃任务并抛出RejectedExecutionException异常。
注:一共有4种基本的拒绝策略,这里采用默认的进行简单的案例讲解。
-
代码1
for (int i = 0; i <7 ; i++) {
Thread thread = new Thread(new MyRunnable());
threadPoolExecutor.execute(thread);
System.out.println(
"当前核心线程数:"+threadPoolExecutor.getCorePoolSize()
+" 当前池中线程数:"+threadPoolExecutor.getPoolSize()
+" 当前阻塞队列任务数:"+threadPoolExecutor.getQueue().size());
}
threadPoolExecutor.shutdown();
/*
执行结果:
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:0
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:2
当前核心线程数:1 当前池中线程数:2 当前阻塞队列任务数:2
当前核心线程数:1 当前池中线程数:3 当前阻塞队列任务数:2
Exception in thread "main"java.util.concurrent.RejectedExecutionException
*/
- 分析1
第一个任务到来时,线程池为空,直接创建核心线程来处理任务
第二个任务到来时,因为核心线程已满,则将该任务放入阻塞队列中
第三个任务到来时,第一个任务执行完毕,取出阻塞队列中的第二个任务来执行,将第三个任务加入阻塞队列
第四个任务到来时,因为第二个任务未执行完毕,因此加入阻塞队列中
第五个任务到来时,因为阻塞队列已满,则创建救急线程来执行第三个任务,将第五个任务加入阻塞队列
第六个任务到来时,因为阻塞队列已满,则创建救急线程来执行第四个任务,将第六个任务加入阻塞队列
第七个任务到来时,因为阻塞队列已满并且最大线程数已满,则新任务无法处理,调用AbortPolicy处理,抛异常
- 代码2
for (int i = 0; i <6 ; i++) {
Thread thread = new Thread(new MyRunnable());
threadPoolExecutor.execute(thread);
System.out.println(
"当前核心线程数:"+threadPoolExecutor.getCorePoolSize()
+" 当前池中线程数:"+threadPoolExecutor.getPoolSize()
+" 当前阻塞队列任务数:"+threadPoolExecutor.getQueue().size());
}
Thread.sleep(2000);
System.out.println(
"当前核心线程数:"+threadPoolExecutor.getCorePoolSize()
+" 当前池中线程数:"+threadPoolExecutor.getPoolSize()
+" 当前阻塞队列任务数:"+threadPoolExecutor.getQueue().size());
threadPoolExecutor.shutdown();
/*
执行结果:
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:0
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:2
当前核心线程数:1 当前池中线程数:2 当前阻塞队列任务数:2
当前核心线程数:1 当前池中线程数:3 当前阻塞队列任务数:2
当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:0
*/
- 分析2
前六行结果同上
第七行结果:由于此时线程任务执行完后,睡了2秒,
此时由于两个救急线程完成任务后1秒没有新任务,则救急线程销毁
线程池中只剩下核心线程
最后
以上就是懦弱荷花为你收集整理的ThreadPoolExecutor基本介绍+简单案例的全部内容,希望文章能够帮你解决ThreadPoolExecutor基本介绍+简单案例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复