ThreadPoolExecutor 构造器
int corePloolSize
核心池大小int maximumPoolSize
最大池大小long keepAliveTime
持续活跃的时间TimeUnit unit
时间单位Queue workQueue
任务队列
线程池工作流程
线程池饱和策略
- RejectedExecutionHandler(饱和策略)
当队列和线程池都满了,此时线程池处于饱和状态
,根据线程池的工作原理,线程池饱和时,应交由饱和策略来处理,即是:如何来处理新提交的任务
。
以下是 JDK1.5 提供的四种策略
- AbortPolicy:直接抛出异常 RejectedExecutionException
- CallerRunsPolicy:使用调用者所在线程来运行任务
- DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
- DiscardPlicy:不处理,丢弃掉
当然也可以根据应用场景需要来实现 RejectedExecutionHandler 接口自定义策略。如记录日志或持久化不能处理的任务。
示例代码
public class TestMain {
public static void main(String[] args) {
//{ps} 阻塞队列大小
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1);
//{ps} 创建一个内部类(静态内部类)
//new ThreadPoolExecutor.AbortPolicy(); //{ps}拒绝策略(默认)
//{ps} 使用调用者所在的线程来执行。(造成调用者做不别的事情)
// RejectedExecutionHandler handler =
// new ThreadPoolExecutor.CallerRunsPolicy();
//{ps} 把这个任务丢弃掉 (扔垃圾桶)
RejectedExecutionHandler handler =
new ThreadPoolExecutor.DiscardPolicy();
Executor exec = new ThreadPoolExecutor(
1, 2, 10,
TimeUnit.SECONDS, queue,
Executors.defaultThreadFactory(),
handler );
//{1} 核心池不满, 它会创建线程来执行.
exec.execute( new MyTask("找一只猫", 20000) );
//{2} 核心池已满, 放入阻塞队列 (阻塞队列只能容一个任务)
exec.execute( new MyTask("找一条狗", 10000) );
//{3} 总线程数未满, 创建新线程来执行任务。(最多请4个人)
exec.execute( new MyTask("接一个客人", 5000) );
//{4} 总线程数达到饱和状态 -----> 执行默认饱和策略。
// 抛出一个拒绝执行异常。
exec.execute( new MyTask("送份快递", 6000) );
//{5} 引起主线程阻塞。
System.out.println("{Main} 043 行。");
}
}
class MyTask implements Runnable{
private String name; //{1}任务的名称
private int time; //{2}执行时间
public MyTask(String name, int time) {
this.name = name;
this.time = time;
}
@Override
public void run() {
String thName = Thread.currentThread().getName();
System.out.printf("{%s}正在执行:%s\n", thName, name);
try { Thread.sleep( time ); }
catch (InterruptedException e) {}
System.out.printf("{%s}执行完成:%s\n", thName, name);
}
}