ExecutorService接口的使用

ExecutorService中有很多工具方法,在前面的文章中提过一些,这里将对剩余方法的功能进行介绍。

invokeyAny()和invokeAll()具有阻塞特性

invokeAny(Collection<? extends Callable> tasks)

取得第一个完成任务的结果值,当第一个任务执行完成后,会调用interrupt()方法将其他任务中断,所以在这些任务中可以结果if(Thread.currentThread().isInterrupted()==true)代码来决定任务是否继续
1、其他线程无if(Thread.currentThread().isInterrupted()==true)代码,已经获得第一个运行的结果值后,其他线程继续运行
2、其他线程有if(Thread.currentThread().isInterrupted()==true)代码,已经获得第一个运行的结果值后,其他线程用throw new InterruptedException()代码则这些线程中断,虽然throw 抛出了异常。但在主线程中并不能捕获到异常,如果想捕获异常,则需要在Callable中使用try-catch显示进行捕获。

如果invokeyAny()执行慢的任务发生异常,默认情况下在主线程中捕获不到异常信息,只能在当前任务中显示的使用try-catch进行捕获
如果invokeyAny()执行快的任务发生异常,默认情况下在主线程中捕获不到异常信息,除非在当前任务中显示的使用try-catch进行捕获,该方法还会等待执行慢的任务返回结果值。
【先出现异常而不影响后面的任务取值的原理在源码中一直判断没有正确的返回值,如果直到最后都没有获得返回值则抛出ExecutionException,这个异常的内容是最后出现的异常。比如A、B、C这三个任务一起被执行,都出现了异常,则最终的异常就是在最后出现的异常】

invokeAny(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)

指定时间内取得第一个先执行完任务的结果值
在出现超时异常时,可以将if(Thread.currentThread().isInterrupted()==true)判断和throw new InterruptedException()结合以使线程中断执行

invokeAll(Collection<? extends Callable> tasks)

等待全部线程执行完毕后,取得全部完成任务的结果值。
如果有任务执行时异常,则在对应的get()方法时抛出

invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)

如果全部任务在指定时间内没有完成,则出现异常(CancallationException)
如果正常执行完成的任务,可以通过对应的get()方法获取到返回值,没有在指定时间内执行完的任务则抛出CancallationException异常。