正文
任务执行抛出了异常,get方法会将异常包装为ExecutionException重新抛出,通过异常的getCause方法可以获取原异常
任务被取消了,get方法会抛出异常CancellationException
如果调用get方法的线程被中断了,get方法会抛出InterruptedException。
Future是一个重要的概念,是实现"任务的提交"与"任务的执行"相分离的关键,是其中的"纽带",任务提交者和任务执行服务通过它隔离各自的关注点,同时进行协作。
基本用法
基本示例
说了这么多接口,具体怎么用呢?我们看个简单的例子:
public class BasicDemo {
static class Task implements Callable
{
@Override
public Integer call() throws Exception {
int sleepSeconds = new Random().nextInt(1000);
Thread.sleep(sleepSeconds);
return sleepSeconds;
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future
future = executor.submit(new Task());
// 模拟执行其他任务
Thread.sleep(100);
try {
System.out.println(future.get());
} catch (ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
}
我们使用了工厂类Executors创建了一个任务执行服务,Executors有多个静态方法,可以用来创建ExecutorService,这里使用的是:
public static ExecutorService newSingleThreadExecutor()
表示使用一个线程执行所有服务,后续我们会详细介绍Executors,注意与Executor相区别,后者是单数,是接口。
不管ExecutorService是如何创建的,对使用者而言,用法都一样,例子提交了一个任务,提交后,可以继续执行其他事情,随后可以通过Future获取最终结果或处理任务执行的异常。
最后,我们调用了ExecutorService的shutdown方法,它会关闭任务执行服务。
ExecutorService的更多方法
前面我们只是介绍了ExecutorService的三个submit方法,其实它还有如下方法:
public interface ExecutorService extends Executor {
void
shutdown
();
List
shutdownNow
();
boolean
isShutdown
();
boolean
isTerminated
();
boolean
awaitTermination
(long timeout, TimeUnit unit)
throws InterruptedException;
List
>
invokeAll
(Collection extends Callable
> tasks)
throws InterruptedException;
List
>
invokeAll
(Collection extends Callable
> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
T
invokeAny
(Collection extends Callable
> tasks)
throws InterruptedException, ExecutionException;
T
invokeAny
(Collection extends Callable
> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
有两个关闭方法,shutdown和shutdownNow,区别是,shutdown表示不再接受新任务,但已提交的任务会继续执行,即使任务还未开始执行,shutdownNow不仅不接受新任务,已提交但尚未执行的任务会被终止,对于正在执行的任务,一般会调用线程的interrupt方法尝试中断,不过,线程可能不响应中断,shutdownNow会返回已提交但尚未执行的任务列表。
shutdown和shutdownNow不会阻塞等待,它们返回后不代表所有任务都已结束,不过isShutdown方法会返回true。调用者可以通过awaitTermination等待所有任务结束,它可以限定等待的时间,如果超时前所有任务都结束了,即isTerminated方法返回true,则返回true,否则返回false。
ExecutorService有两组批量提交任务的方法,invokeAll和invokeAny,它们都有两个版本,其中一个限定等待时间。
invokeAll等待所有任务完成,返回的Future列表中,每个Future的isDone方法都返回true,不过isDone为true不代表任务就执行成功了,可能是被取消了,invokeAll可以指定等待时间,如果超时后有的任务没完成,就会被取消。
而对于invokeAny,只要有一个任务在限时内成功返回了,它就会返回该任务的结果,其他任务会被取消,如果没有任务能在限时内成功返回,抛出TimeoutException,如果限时内所有任务都结束了,但都发生了异常,抛出ExecutionException。