1.get和interrupt
private static void testGet() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
//==========================================
System.out.println("=========I will be printed quickly.==========");
//==========================================
Thread callerThread = Thread.currentThread();
new Thread(() -> {
try {
TimeUnit.MILLISECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
//打断了callerThread和future.get()的阻塞
//要注意,get()阻塞的是调用线程,而不是线程池中的线程
//对线程池里面的线程没有影响,线程池里面的线程还在执行中
callerThread.interrupt();
}).start();
//get()时,会阻塞调用线程
Integer result = future.get();
System.out.println(result);
}
2.GetWithTimeOut
private static void testGetWithTimeOut() throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("====== The time is longer than timeOut ========");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
//该方法对调用者是超时退出的
//特别要注意,对线程池中的线程没有任何影响,线程还是会一直运行
//如果需要取消线程池中的线程执行,需要用到cancel,并且此线程是可被中断的
Integer result = future.get(5, TimeUnit.SECONDS);
System.out.println(result);
}
}
3.cancel
简单来说,传入false参数只能取消还没有开始的任务,若任务已经开始了,就任由其运行下去。
当创建了Future实例,任务可能有以下三种状态:
- 等待状态:此时调用cancel()方法不管传入true还是false都会标记为取消,任务依然保存在任务队列中,但当轮到此任务运行时会直接跳过。
- 完成状态:此时cancel()不会起任何作用,因为任务已经完成了。
- 运行中:此时传入true会中断正在执行的任务,传入false则不会中断。
总结:
-
Future.cancel(true)适用于:
长时间处于运行的任务,并且能够处理interruption -
Future.cancel(false)适用于:
(1) 未能处理interruption的任务
(2) 不清楚任务是否支持取消
(3) 需要等待已经开始的任务执行完成
3.1 任务完成,取消
private static void testCancel_1() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> {
TimeUnit.SECONDS.sleep(5);
return 5;
});
System.out.println(future.get());
System.out.println(future.cancel(true));
}
}
//输出:
5
false
3.2 任务完成,取消后,再次取消
private static void testCancel_1() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> {
try{
TimeUnit.SECONDS.sleep(5);
}catch (InterruptedException e){
System.out.println( LocalTime.now() +": =========");
}
System.out.println( LocalTime.now() +": *********");
return 5;
});
TimeUnit.MILLISECONDS.sleep(10);
System.out.println( LocalTime.now() +": " + future.cancel(true));
System.out.println(LocalTime.now() +": " + future.cancel(true));
// System.out.println(future.get());
}
//输出:
11:31:13.029: true
11:31:13.029: false
11:31:13.029: =========
11:31:13.030: *********
3.3 对没有可中断的任务进行取消
private static void testCancel_3() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> {
while(true) {
System.out.println("=====");
}
});
TimeUnit.MILLISECONDS.sleep(10);
System.out.println(future.cancel(true));
System.out.println(future.isDone());
System.out.println(future.isCancelled());
}
//输出:
//发现会一直打印,任务并没有被取消
//而cancel、isDone、isCancelled都返回了true
//=====
//=====
//true
//true
//true
//=====
....
3.4 暴力全部停止不可中断的任务
private static void testCancel_1() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
Future<Integer> future = executorService.submit(() -> {
while(true) {
System.out.println("=====");
}
});
TimeUnit.MILLISECONDS.sleep(10);
System.out.println(future.cancel(true));
System.out.println(future.isDone());
System.out.println(future.isCancelled());
}
//输出:
//发现任务会取消
//cancel、isDone、isCancelled都返回了true
//=====
//=====
//true
//true
//true
//=====
3.5 interrupted配合cancel
private static void testCancel_1() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> {
while(!Thread.interrupted()) {
}
System.out.println( LocalTime.now() +": *********");
return 5;
});
TimeUnit.MILLISECONDS.sleep(10);
System.out.println( LocalTime.now() +": " + future.cancel(true));
System.out.println(LocalTime.now() +": " + future.cancel(true));
}
//输出:
13:36:31.089: true
13:36:31.089: *********
13:36:31.089: false
3.6 cancel之后,进行get
private static void testCancel_1() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> {
while(!Thread.interrupted()) {
}
System.out.println( LocalTime.now() +": *********");
return 5;
});
TimeUnit.MILLISECONDS.sleep(10);
System.out.println( LocalTime.now() +": " + future.cancel(true));
System.out.println(future.get());
}
//输出:
13:38:17.640: true
13:38:17.640: *********
Exception in thread "main" java.util.concurrent.CancellationException
at java.util.concurrent.FutureTask.report(FutureTask.java:121)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.testCancel_1(ExecutorServiceExample1.java:35)
at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.main(ExecutorServiceExample1.java:16)