一、FutureTask
一种可取消的异步计算。这个类提供了Future的基本实现,提供了启动和取消计算、查询计算是否完成以及检索计算结果的方法。只有在计算完成后才能检索结果;如果计算尚未完成,则get方法将被阻塞。一旦计算完成,就无法重新启动或取消计算(除非使用runAndReset调用计算)。
FutureTask可以用于包装Callable或Runnable对象。因为FutureTask实现了Runnable,所以FutureTasks可以提交给Executor执行。
二、FutreTask类图
三、具体使用代码
public class AsyncThreadTest {
public static void main(String[] args) {
List<FutureTask<Integer>> futureTasks = new ArrayList<>();
// 通过线程池执行
int processors = Runtime.getRuntime().availableProcessors();
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(processors * 2);
executor.setMaxPoolSize(processors * 4);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-pool-");
executor.setKeepAliveSeconds(0);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
for (int i = 0; i < 3; i++){
// 创建异步任务
FutureTask<Integer> asyncTask = new FutureTask<>(new MyTask("任务" + (i + 1)));
futureTasks.add(asyncTask);
executor.submit(asyncTask);
}
System.out.println("主线程开始执行:" + LocalDateTime.now());
// 遍历异步任务执行结果
for(FutureTask<Integer> task : futureTasks){
Integer result = null;
try {
// get方法会阻塞,直到获取结果为止
//result = task.get();
// get方法会阻塞,超时为止
result = task.get(10, TimeUnit.SECONDS);
} catch (InterruptedException e) { // 线程被中断将会进入此处
System.out.println("中断异常");
} catch (ExecutionException e) { // 线程执行异常将会进入此处
System.out.println("执行异常");
} catch (TimeoutException e){ // 获取结果超时将会进入此处
System.out.println("超时异常");
}
System.out.println(result);
}
}
private static class MyTask implements Callable<Integer>{
// other
private final String taskName;
public MyTask(String taskName){
this.taskName = taskName;
}
@Override
public Integer call() throws Exception {
System.out.println(taskName + ",开始执行");
Thread.sleep(20000);
return 1;
}
}
}
四、常用方法
- isCancelled():在任务正常完成之前取消则返回true
- isDone():任务完成返回true
- cancel(boolean mayInterruptIfRunning):尝试取消执行此任务。如果任务已经完成、已经取消或由于其他原因无法取消,则此尝试将失败。如果成功,并且在调用cancel时此任务尚未启动,则不应运行此任务。如果任务已经启动,那么mayInterruptIfRunning参数确定是否应该中断执行此任务的线程以尝试停止任务。
- get():等待任务执行完成返回结果
- get(long timeout, TimeUnit unit):指定时间内等不到结果,将抛超时异常