1、FutureTask
FutureTask 要和 Callable 配合使用,Callable接口解决了Runnbale无返回值的问题,Callable重新定一个一个有返回值的call()方法用来对标Runable的run()方法。
使用Callable创建一个FutureTask实例:
FutureTask<Boolean> future = new FutureTask<>(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return true;
}
});
通过new一个对象的方法可以直接创建一个FutureTask实例,如果直接调用run方法将直接在当前线程中运行,不会开启新线程。
使用ExecutorService或者线程可以让FutureTask进行托管进行,示例如下:
//托管给线程池处理
Future<?> futureResult = Executors.newCachedThreadPool().submit(future);
//托管给单独线程处理
new Thread(future).start();
因为FutureTask继承了Runnable接口,所以它可以通过new Thread()的方式进行运行,再由future变量来检索结果值或者取消任务等操作,通过线程池托管的方式也可以适用。
取消任务
遇到特殊情况时需要对没有运行的或者已经运行的任务进行取消操作,这时可以调用cancel()方法,取消方法有一个布尔类型的参数mayInterruptIfRunning;当值为ture时将尝试中断托管的线程(调用托管线程的interrupt尝试中断)。
取消任务使用的是线程的中断操作,如果任务是可取消的,在任务中存在阻塞线程的地方需要加上InterruptedException的异常捕获来处理中断异常或者在任务可取消点使用Thread.currentThread().isInterrupted()方法来判断任务是否已经发送的中断请求以正常取消任务。
检索结果值
使用FutureTask的一个重要目的是为了能获取到任务的结果值,使用Callable使用一个任务调用点时可以在任务中返回一个引用类型。
在FutureTask内部使用outcome变量存储Callable的结果,调用FutureTask.get()方法将检索结果值,但get()方法也会阻塞调用线程直到任务执行完成或者取消。
get()方法还可以通过设置超时时间来指定等待的时长,超过等待时间后将会抛出TimeoutException异常。