线程池参数
1,线程池创建
import java.util.concurrent.ThreadPoolExecutor;
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(7个参数);
2,线程池参数介绍
int corePoolSize:核心线程数;
int maximumPoolSize:最大线程数;
long keepAliveTime:线程空闲的存活时间;
TimeUnit unit:空闲时存活时间的单位,秒分时天月等;
BlockingQueue<Runnable> workQueue:工作队列;
ThreadFactory threadFactory:创建线程的工厂;
RejectedExecutionHandler handler:拒绝策略;
3,测试
3.1,需要执行的任务
public class MyTask implements Runnable {
/**
* 标识当前任务的序号
*/
private int no;
public MyTask(int no) {
this.no = no;
}
@Override
public void run() {
System.out.println(String.format("任务" + no + "开始执行,当前时间:" + MyUtil.getCurrentChineseTime(new Date())));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException("任务" + no + "在sleep时出错啦");
}
System.out.println("任务" + no + "完成,当前时间:" + MyUtil.getCurrentChineseTime(new Date()));
}
}
3.2,创建线程池,并执行10个任务
/**
* 1,核心线程数:2
* 2,最大线程数:4
* 3,非核心线程空闲时的存活时间:1秒
* 4,非核心线程空闲时的存活时间单位:秒
* 5,工作队列:有界队列(FIFO,界限为3,即最多缓存3个任务)
* 6,创建线程的工厂:此处为默认工厂Executors.defaultThreadFactory()
* 7,拒绝策略:此处为默认拒绝策略defaultHandler,即new AbortPolicy(),直接丢弃任务并抛出RejectedExecutionException异常
*/
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3));
// 创建10个待执行的任务,任务序号0-9
List<MyTask> myTaskList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
MyTask myTask = new MyTask(i);
myTaskList.add(myTask);
}
// 同步(同时)执行任务0-任务9
for (MyTask myTask : myTaskList) {
threadPool.execute(myTask);
}
3.3,运行结果
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.learnjava.threadPool.threadpool.MyTask@5451c3a8 rejected from java.util.concurrent.ThreadPoolExecutor@2626b418[Running, pool size = 4, active threads = 4, queued tasks = 3, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at com.learnjava.threadPool.threadpool.ThreadPoolLearn.main(ThreadPoolLearn.java:31)
任务1开始执行,当前时间:2024-02-16 17:19:30
任务6开始执行,当前时间:2024-02-16 17:19:30
任务0开始执行,当前时间:2024-02-16 17:19:30
任务5开始执行,当前时间:2024-02-16 17:19:30
任务0完成,当前时间:2024-02-16 17:19:32
任务5完成,当前时间:2024-02-16 17:19:32
任务1完成,当前时间:2024-02-16 17:19:32
任务2开始执行,当前时间:2024-02-16 17:19:32
任务6完成,当前时间:2024-02-16 17:19:32
任务3开始执行,当前时间:2024-02-16 17:19:32
任务4开始执行,当前时间:2024-02-16 17:19:32
任务2完成,当前时间:2024-02-16 17:19:34
任务3完成,当前时间:2024-02-16 17:19:34
任务4完成,当前时间:2024-02-16 17:19:34
3.4,结果分析
任务0到任务9同时交给线程池处理,线程池大差不差按时间先后顺序执行如下:
一、线程池创建了2个核心线程执行任务1、任务6;
二、线程池将任务2、任务3、任务4放进了工作队列中,等待执行;
三、线程池创建2个非核心线程执行任务0、任务5;
四、线程池开始处理任务7,但是此时没有空闲线程,4个线程(2个核心线程和2个非核心线程)都在执行任务中,且工作队列已经满了(只能放3个任务),所以执行拒绝策略,预定的策略是直接丢弃且抛出RejectedExecutionException异常;任务8、任务9同理;
五、差不多2秒(任务时间为2秒)后,线程池中的4个线程其中有个执行完成了,则取出队列中的第一个任务(此处认为是任务2)执行,同理有线程空闲了就取出工作队列中的其他两个任务(任务3、任务4)执行;
六、非核心线程,处于空闲状态,时间达到设定的空闲时间时会销毁(或其他操作以节约资源)。
4,总结
先创建核心线程执行任务,核心线程数没到时,即使之前创建的核心线程空闲了也会继续创建核心线程执行新任务,直到核心线程的数量达到核心线程数;
核心线程数到了时,核心线程会一直存活;即使空闲也不会直接执行新任务,要等新任务加入工作队列后,才从工作队列取出来执行;
工作队列满了后,会创建非核心线程来执行新任务,核心线程数量+非核心线程数量不能超过总数,超过后执行拒绝策略;
看下debug的情况:
4.1,创建核心线程
4.2,任务加入工作队列
4.3,debug总结
a,核心线程数量没到时,即使之前创建的核心线程空闲了,也会重新创建一个核心线程来执行任务,不会使用之前创建的核心线程来执行;
b,核心线程到数量后,会一直存活,即使空闲了也不会直接执行新任务,而是等到新任务加入到工作队里后从队列里面取出来执行;