问:线程池中线程用完了怎么办?
答:放到队列中
问:那队列也用完了呢?
。。。。
下面就是饱和策略登场了
首先设置饱和策略的方式,就是下面这个了
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
1、Abort策略
这个也是线程池默认的饱和策略,该策略是抛出一个RejectedExecutionException的异常,调用者可以捕获这个异常然后进行处理,代码就是下面1对应的那个方法
输出结果:从结果中可以看到抛出异常,然后停止继续执行
2、CallerRunsPolicy(调用者运行)
这个策略不会抛出异常也不会抛弃任务,而是回到调用者线程中,由调用者来执行,降低新任务的流量,同时给线程池执行任务的时间,但是这种策略要小心如果持续过载最终可能会导致整个服务器在高负载下。
对应代码下面callerruns()方法:
运行结果:这里只截取了部分打印结果,但也可以清晰地看出来,主线程在提交任务的过程中被暂停任务线程的打印结果穿插其中,注意:我这里任务线程执行过程中有sleep时间所以正常情况下主线程的循环肯定会比第一个执行的任务打印之前完成
3、DiscardPolicy(抛弃策略)
不言而喻就是如果任务队列满了新来的任务会被直接抛弃掉
4、DiscardOldestPolicy(抛弃最旧的)
也很好理解有新的任务进来抛弃最先进入队列的任务(即马上要执行的任务),所以这里要注意一下此策略不能和优先队列在一起使用那样优先级别最高的会被抛弃的
public class ThreadPoolTest {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,8,0L,
TimeUnit.MILLISECONDS,new LinkedBlockingDeque<>(6));
public static void main(String[] args) {
abort(); ----------- 1
discard();------------2
discardpolicyoldest();-------------3
callerruns();-------------------4
}
//调用者运行
//这里就是由主线程运行,这时候就会暂时提交任务
private static void callerruns() {
ThreadPoolTest threadPoolTest = new ThreadPoolTest();
threadPoolTest.executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
for (int i = 0; i < 50; i++) {
System.out.println("main:"+i);
threadPoolTest.executor.execute(new PrintTask(i));
}
}
//满了之后抛弃掉最新的提交的
//所以这里要注意优先策略不要这个饱和策略一起使用
private static void discardpolicyoldest() {
ThreadPoolTest threadPoolTest = new ThreadPoolTest();
threadPoolTest.executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
for (int i = 0; i < 50; i++) {
System.out.println("main:"+i);
threadPoolTest.executor.execute(new PrintTask(i));
}
}
//满了之后再提交就抛弃掉
private static void discard() {
ThreadPoolTest threadPoolTest = new ThreadPoolTest();
threadPoolTest.executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
for (int i = 0; i < 50; i++) {
System.out.println("main:"+i);
threadPoolTest.executor.execute(new PrintTask(i));
}
}
//abort策略跑出一个异常
private static void abort() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,8,0L,
TimeUnit.MILLISECONDS,new LinkedBlockingDeque<>(5));
for (int i = 0; i < 100; i++) {
executor.execute(new PrintTask(i));
}
}
}