java.util.concurrent.ExecutorService

原创
2014/06/19 22:30
阅读数 681

Thread提供了线程的实现,Executor(点击查看源码) 提供了任务被执行的策略接口,那么更深一步的任务执行的整个过程和生命周期,又是如何来体现的呢? 接下来,我们看看ExecutorService

上源代码:

public interface ExecutorService extends Executor {
    void shutdown();

    List<Runnable> shutdownNow();

    boolean isShutdown();

    boolean isTerminated();

    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    <T> Future<T> submit(Callable<T> task);

    <T> Future<T> submit(Runnable task, T result);

    Future<?> submit(Runnable task);

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}


void shutdown();

void shutdown();

解读:将执行平缓的关闭过程: 

  • 不再接受新的任务

  • 同时等待那些已经提交的任务完成

  • 包括等待那些尚未开始执行的任务到全部完成

注意:如果在执行的某些线程无法结束,例如一直处于循环或者阻塞或者死锁等异常,那么该方法将会一直等待线程执行完成。这是不是很糟糕呢?


List<Runnable> shutdownNow();

List<Runnable> shutdownNow();

返回: 那些还没有来得及被执行的任务

解读: 将执行粗暴的关闭过程:

  • 不再接受新的任务

  • 尝试取消所有运行中的任务,就是发送interrupt信号

  • 不再启动队列中尚未开始的任务

注意:比较上一个方法shutdown,这个会更霸气一点,并且会直接尝试取消运行中的任务,注意尝试指的是Interrupt。所以如果某个线程,无法响应Interrupt,那么这个方法仍然无法达到预期的目标。所以切记再写runnable的时候要记得响应InterrptException,否则会导致线程池无法正常回收。

是不是很想再加一个shutdownRightNow()的方法?


boolean isShutdown();

boolean isShutdown();

返回:是否正在关闭,只有当执行过shutdown或者shutdownNow时才会返回true.


boolean isTerminated();

boolean isTerminated();

返回: 所有任务是否已经全部结束了

注意: 可能会永远返回false哦,想想为什么

  • shutdown或者shutdownNow从为被执行过时,将永远返回false

  • shutdown或者shutdownNow被执行过,但又线程永远未能正常结束,将永远返回false


boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

参数: 超时时间和时间单位

返回: 所有任务是否已经全部结束了

异常: InterruptedExcetpion,当阻塞等待中,线程被Interrupt

解读: 阻塞的方式等待所有线程被执行完成,除非

  • 所有任务都完成了

  • Timeout,超过了最大等待时间

  • 本线程被Interrupt

这三种情况下,会返回或者抛异常。

    

面试点:请说明线程池中 shutdown, shutdownNowisTerminated和 awaitTermination 的各自特点和使用时的注意点。


<T> Future<T> submit(Callable<T> task);

<T> Future<T> submit(Callable<T> task);

参数: Callable<T> task点击查看源码

返回: 执行的结果Future (点击查看源码)


<T> Future<T> submit(Runnable task, T result);

<T> Future<T> submit(Runnable task, T result);

参数: Runnable task待执行的任务, T result,具体的执行结果范型

返回: 执行的结果Future


Future<?> submit(Runnable task);

Future<?> submit(Runnable task);

参数: Runnable  task 被执行的任务

返回: 执行的结果Future


以上三个方法是,比较类似的三个执行当个任务的方法,再加上父类中execute方法,是不是齐了呢?带结果返回的和不带结果返回的,带指定返回参数的和不带返回参数的。


<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

参数:Callable的集合 tasks.

返回:执行结果的集合Future

异常:InterruptedException, 如果该线程被中断了。

注意:所有任务很又可能会乱续执行


<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

参数:Callable的集合 tasks. 等待时间

返回:执行结果的集合Future

异常:InterruptedException, 如果该线程被中断了。

注意:所有任务很又可能会乱续执行,当

  • 所有任务都被提交了

  • 提交超时

将返回结果


<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;

<T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

参数:Callable的集合 tasks.

返回:返回第一个执行完成的任务,其余的将被取消

异常:InterruptedException, 如果该线程被中断了。ExecutionException执行过程中的异常

注意:所有任务很又可能会乱续执行,任何一个都又可以最先执行完成。


<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

<T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;

参数:Callable的集合 tasks. 等待时间

返回:返回第一个执行完成的任务,其余的将被取消

异常:

  • InterruptedException, 如果该线程被中断了;

  • ExecutionException 执行过程中的异常;

  • TimeoutException 超时;

注意:所有任务很又可能会乱续执行,任何一个都又可以最先执行完成


几乎扩展了父接口所有执行场景提交单个还是提交多个,是否超时,是且的执行关系还是或的执行关系。



回答上期的问题:

Executor, 为什么这个接口只有一个方法。为什么ExecutorService,会去继承这个接口,而不是直接把这个方法纳入到自己的接口中?

  1. 关注点不同,Executor更关注执行的策略,而ExecutorService更关注执行当中的生命周期。

  2. 场景不同,Executor使用的场景可能会更简单,而ExecutorSerivce使用的场景会更复杂

  3. 扩展性较好,如果有其他的场景,ExecutorService并不太适合时,那么使用者可以通过自己扩展Executor来实现

通常一个好的接口设计会直接影响到你的程序设计,而如何抽象接口更是考验一个设计者功底。




展开阅读全文
加载中
点击加入讨论🔥(1) 发布并加入讨论🔥
打赏
1 评论
1 收藏
1
分享
返回顶部
顶部