一、流程:
创建一个任务时,先判断线程池中已有的线程数是否已经超过核心线程数,如果没有,则创建任务;
如果超过核心线程数,去阻塞队列中,看阻塞队列是否已满,如果没满,则放入阻塞队列中;
如果阻塞队列已满,则判断当前线程数是否超过最大线程数,如果没超过,则创建一个新的线程;
如果超过最大线程数,则走异常处理流程(直接抛异常;不处理,丢弃;将阻塞队列中最早的任务丢弃,然后将其放入阻塞队列)
二、异常处理方法:
(一)线程池提交时submit:
1、try catch
2、用Future作为submit的结果,用future.get()方法,接收抛出的异常(future.get()方法要加try catch)
(二)线程中处理异常:
处理未捕获到的异常)
Thread t = new Thread(r);
t.setUncaughtExceptionHandler(
(t1, e) -> {
System.out.println(t1.getName() + "线程抛出的异常"+e);
});
return t;
});
(三)重写ThreadExecutorPool的afterExecute方法 处理传递的异常引用!
三、线程池:
newFixedTreadPool固定线程数线程池
- 核心线程数和最大线程数大小一样
- 没有所谓的非空闲时间,即keepAliveTime为0
- 阻塞队列为无界队列LinkedBlockingQueue
newCachedTreadPool(可缓存线程的线程池)
- 核心线程数为0
- 最大线程数为Integer.MAX_VALUE
- 阻塞队列是SynchronousQueue
- 非核心线程空闲存活时间为60秒
- 提交任务
- 因为没有核心线程,所以任务直接加到SynchronousQueue队列。
- 判断是否有空闲线程,如果有,就去取出任务执行。
- 如果没有空闲线程,就新建一个线程执行。
- 执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续活下去;否则,被销毁
newSingleTreadExecutor单线程线程池
- 核心线程数为1
- 最大线程数也为1
- 阻塞队列是LinkedBlockingQueue
- keepAliveTime为0
newScheduledThreadPool(定时及周期执行的线程池)
- 最大线程数为Integer.MAX_VALUE
- 阻塞队列是DelayedWorkQueue
- keepAliveTime为0
- scheduleAtFixedRate() :按某种速率周期执行
- scheduleWithFixedDelay():在某个延迟后执行
工作机制
- 添加一个任务
- 线程池中的线程从 DelayQueue 中取任务
- 线程从 DelayQueue 中获取 time 大于等于当前时间的task
- 执行完后修改这个 task 的 time 为下次被执行的时间
- 这个 task 放回DelayQueue队列中