我们知道在调用执行器的shutdown()方法后,再向执行器提交任务会被拒绝。执行器框架为我们提供了一个类RejectedExecutionHandler,来让我们自定义一些被拒绝任务的处理逻辑。
首先实现自定义的拒绝任务处理逻辑,继承RejectedExecutionHandler,并实现rejectedExecution方法。
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 创建执行器拒绝任务处理器
*
* Created by hadoop on 2016/11/3.
*/
public class RejectedTaskController implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.printf("RejectedTaskController: The task %s has been rejected.\n", r.toString());
System.out.printf("RejectedTaskController: Executor is %s\n", executor.toString());
System.out.printf("RejectedTaskController: Executor terminating: %s\n", executor.isTerminating());
System.out.printf("RejectedTaskController: Executor terminated: %s\n", executor.isTerminated());
}
}
模拟一个任务线程,实现Runnable接口。
import java.util.concurrent.TimeUnit;
/**
*
* Created by hadoop on 2016/11/3.
*/
public class Task implements Runnable {
private String name;
public Task(String name) {
this.name = name;
}
@Override
public void run() {
long duration = (long)(Math.random() * 10);
System.out.printf("Task: %s will run during %d seconds\n", name, duration);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return this.name;
}
}
在主线程类中,首先初始化自定义的被拒绝任务处理器,然后把它赋值给执行器。模拟在shutdown()方法后提交任务,并观察结果。
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 处理在执行器中被拒绝的任务
*
* 我们使用shutdown方法来关闭执行器,但是如果当前有正在执行的任务,执行器会等待任务执行完成才会关闭。
* 但这个时候执行期已经不再接受任何任务了,我们发送任务给执行器会被拒绝。
* ThreadPoolExecutor提供了一套机制了处理这些被拒绝的任务。
*
* 我们定义了一个执行器拒绝任务储丽丽RejectedTaskController.
* 在方法rejectedExecution(Runnable r, ThreadPoolExecutor executor)中处理被拒绝的任务。
*
* 需要通过执行器的setRejectedExecutionHandler(controller)方法来给执行器设置决绝任务处理器类。
*
* 当有任务发送给处理器的时候,会检查处理器是否被shutdown,如果shutdown那么就会调用拒绝任务处理器。
* 如果没有定义这个拒绝任务处理器,那么就会抛出RejectedExecutionException异常。
*
* Created by hadoop on 2016/11/3.
*/
public class Main {
public static void main(String[] args) {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
RejectedTaskController controller = new RejectedTaskController();
executor.setRejectedExecutionHandler(controller);
for (int i = 0; i < 3; i++) {
Task task = new Task("Task" + i);
executor.submit(task);
}
executor.shutdown();
Task task = new Task("RejectTask");
executor.submit(task);
}
}
控制台结果:
RejectedTaskController: The task java.util.concurrent.FutureTask@5d86aad9 has been rejected.
Task: Task1 will run during 2 seconds
Task: Task0 will run during 0 seconds
Task: Task2 will run during 8 seconds
RejectedTaskController: Executor is java.util.concurrent.ThreadPoolExecutor@767ca7f0[Shutting down, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]
RejectedTaskController: Executor terminating: true
RejectedTaskController: Executor terminated: false