专栏名称: 老马说编程
从入门到高级, 深入浅出, 老马和你一起探索编程及计算机技术的本质, 篇篇原创, 用心写作。
目录
相关文章推荐
51好读  ›  专栏  ›  老马说编程

(77) 异步任务执行服务 / 计算机程序的思维逻辑

老马说编程  · 公众号  · 程序员  · 2017-03-02 22:31

正文

请到「今天看啥」查看全文


  • 任务执行抛出了异常,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。







    请到「今天看啥」查看全文