四种拒绝策略如下
* 往线程池中扔4个任务 核心线程数是1 最大线程数是2 队列大小是1
* 仍第一个任务时 先放入阻塞队列,开启一条线程获取该任务执行
* 仍第二个任务时 放入阻塞队列
* 仍第三个任务时 发现核心线程还没有执行完,那新创建线程拿走任务二 并将任务三放入阻塞队列
* 仍第二个任务时 最大线程已满而且还没有执行完,阻塞队列已满 走拒绝策略
代码如下:
package day10.part2;
import java.util.concurrent.*;
/**
* 线程池的拒绝策略
*
* 1、ThreadPoolExecutor.AbortPolicy:
* 丢弃任务并抛出RejectedExecutionException异常。
* 2、ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
* 3、ThreadPoolExecutor.DiscardOldestPolicy:
* 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
* 4、ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
* 这里有main线程处理 将main线程也加入线程池 main线程就由线程池控制
*
* @author xzq
*/
public class ExecutorTest05 {
public static void main(String[] args) {
// abortPolicy();
// discardPolicy();
//callerRunsPolicy();
discardOldestPolicy();
System.out.println("主线程执行完毕!");
}
private static void abortPolicy(){
//创建一个阻塞队列
BlockingQueue<Runnable> blcQ=new ArrayBlockingQueue<>(1);
//创建线程工厂
ThreadFactory threadFactory=new ExecutorTest01.MyThreadFactory();
//创建拒绝策略
RejectedExecutionHandler handler=new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor threadPool=new ThreadPoolExecutor(
1, 2, 5, TimeUnit.SECONDS, blcQ, threadFactory, handler);
System.out.println("线程池创建完毕---------------------------------");
/*
* 往线程池中扔4个任务 核心线程数是1 最大线程数是2 队列大小是1
*
* 仍第一个任务时 先放入阻塞队列,开启一条线程获取该任务执行
* 仍第二个任务时 放入阻塞队列
* 仍第三个任务时 发现核心线程还没有执行完,那新创建线程拿走任务二 并将任务三放入阻塞队列
* 仍第二个任务时 最大线程已满而且还没有执行完,阻塞队列已满 走拒绝策略
*/
for(int i=0;i<4;i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
sleepSeconds(3);
}
});
}
}
private static void discardPolicy(){
//创建一个阻塞队列
BlockingQueue<Runnable> blcQ=new ArrayBlockingQueue<>(1);
//创建线程工厂
ThreadFactory threadFactory=new ExecutorTest01.MyThreadFactory();
//创建拒绝策略
RejectedExecutionHandler handler=new ThreadPoolExecutor.DiscardPolicy();
ThreadPoolExecutor threadPool=new ThreadPoolExecutor(
1, 2, 5, TimeUnit.SECONDS, blcQ, threadFactory, handler);
System.out.println("线程池创建完毕---------------------------------");
/*
* 往线程池中扔4个任务 核心线程数是1 最大线程数是2 队列大小是1
*
* 仍第一个任务时 先放入阻塞队列,开启一条线程获取该任务执行
* 仍第二个任务时 放入阻塞队列
* 仍第三个任务时 发现核心线程还没有执行完,那新创建线程拿走任务二 并将任务三放入阻塞队列
* 仍第二个任务时 最大线程已满而且还没有执行完,阻塞队列已满 走拒绝策略
*/
for(int i=0;i<4;i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
sleepSeconds(3);
}
});
}
}
private static void callerRunsPolicy(){
//创建一个阻塞队列
BlockingQueue<Runnable> blcQ=new ArrayBlockingQueue<>(1);
//创建线程工厂
ThreadFactory threadFactory=new ExecutorTest01.MyThreadFactory();
//创建拒绝策略
RejectedExecutionHandler handler=new ThreadPoolExecutor.CallerRunsPolicy();
ThreadPoolExecutor threadPool=new ThreadPoolExecutor(
1, 2, 5, TimeUnit.SECONDS, blcQ, threadFactory, handler);
System.out.println("线程池创建完毕---------------------------------");
//往线程池中扔4个任务
for(int i=0;i<4;i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
sleepSeconds(3);
}
});
}
}
private static void discardOldestPolicy(){
//创建一个阻塞队列
BlockingQueue<Runnable> blcQ=new ArrayBlockingQueue<>(1);
//创建线程工厂
ThreadFactory threadFactory=new ExecutorTest01.MyThreadFactory();
//创建拒绝策略
//RejectedExecutionHandler handler=new ThreadPoolExecutor.DiscardOldestPolicy();
//自定义拒绝策略
RejectedExecutionHandler handler= new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
/*
* 数据很宝贵,一般是不能扔的 所以要自定义拒绝策略
* 把任务放进缓存redis中,生成一些记录或者打印日志 方便后续开发维护
*/
}
};
/*
* 从redis中拿出走拒绝策略的Runnable r,然后要继续执行的话,就要往线程池中扔
*/
ThreadPoolExecutor threadPool=new ThreadPoolExecutor(
1, 2, 5, TimeUnit.SECONDS, blcQ, threadFactory, handler);
System.out.println("线程池创建完毕---------------------------------");
//往线程池中扔4个任务
for(int i=0;i<4;i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
sleepSeconds(3);
System.out.println(Thread.currentThread().getName()+"花了3秒执行结束!");
}
});
}
//4秒后再扔一个任务给线程池
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.execute(new Runnable() {
@Override
public void run() {
sleepSeconds(5);
System.out.println(Thread.currentThread().getName()+"花了5秒执行结束!");
}
});
}
private static void sleepSeconds(int seconds){
try {
System.out.println(Thread.currentThread().getName()+"正在执行……");
Thread.sleep(seconds*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
数据是非常重要的,拒绝策略大都丢弃了任务,为了记录数据我们可以自定义拒绝策略,如下
//创建拒绝策略
//RejectedExecutionHandler handler=new ThreadPoolExecutor.DiscardOldestPolicy();
//自定义拒绝策略
RejectedExecutionHandler myHandler= new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
/*
* 数据很宝贵,一般是不能扔的 所以要自定义拒绝策略
* 把任务放进缓存redis中,生成一些记录或者打印日志 方便后续开发维护
*/
}
};
/*
* 从redis中拿出走拒绝策略的Runnable r,然后要继续执行的话,就要往线程池中扔
*/
ThreadPoolExecutor threadPool=new ThreadPoolExecutor(
1, 2, 5, TimeUnit.SECONDS, blcQ, threadFactory, myHandler);
System.out.println("线程池创建完毕---------------------------------");