ExecutorService的invokeAny方法
一、此方法获得最先完成任务的结果,即Callable<T>接口中的call的返回值,在获得结果时,会中断其他正在执行的任务
示例代码:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class MyinvokeAny { public static void main(String[] args) { // TODO 自动生成的方法存根 List<Callable<String>> list=new ArrayList<Callable<String>>(); list.add(new MyCallable_iAny1()); list.add(new MyCallable_iAny2()); ExecutorService executor=Executors.newCachedThreadPool(); try { String str=executor.invokeAny(list);//取出第一个执行完的任务时,其他未完成的任务会被中断 System.out.println(str); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (ExecutionException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } class MyCallable_iAny1 implements Callable<String>{ @Override public String call() throws Exception { // TODO 自动生成的方法存根 try{ for(int i=0;i<123456;i++){ for(int j=0;j<123;j++){ if(Thread.currentThread().isInterrupted()){ System.out.println("this is a exception"); throw new InterruptedException("A InterruptedException"); } } } }catch(Exception e){ e.printStackTrace(); throw e; } System.out.println("finish"); return "call_1"; } } class MyCallable_iAny2 implements Callable<String>{ @Override public String call() throws Exception { // TODO 自动生成的方法存根 Thread.sleep(1000); return "call_2"; } }
运行结果:
call_2java.lang.InterruptedException: A InterruptedException this is a exception at myexecutorservice.MyCallable_iAny1.call(myinvokeAny.java:53) at myexecutorservice.MyCallable_iAny1.call(myinvokeAny.java:1) at java.util.concurrent.FutureTask.run(Unknown Source)
二、异常的处理
对于会先完成,但会出现异常的任务,ExecutorService会将关注点换到下一个任务,若果所有的任务都出现异常,那么将会只获得最后一个任务的异常(例如,有3个任务A,B,C,这三个任务都会出现异常,但是只会获得C任务的异常)
示例代码:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class myinvokeAny { public static void main(String[] args) { // TODO 自动生成的方法存根 List<Callable<String>> list=new ArrayList<Callable<String>>(); list.add(new MyCallable_iAny1()); list.add(new MyCallable_iAny2()); ExecutorService executor=Executors.newCachedThreadPool(); try { String str=executor.invokeAny(list);//取出第一个执行完的任务时,其他未完成的任务会被中断 System.out.println(str); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (ExecutionException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } class MyCallable_iAny1 implements Callable<String>{ @Override public String call() throws Exception { // TODO 自动生成的方法存根 Thread.sleep(2000); System.out.println("finish"); return "call_1"; } } class MyCallable_iAny2 implements Callable<String>{ @Override public String call() throws Exception { // TODO 自动生成的方法存根 Thread.sleep(1000); if(true){ throw new Exception("myException_B"); } return "call_2"; } }
运行结果:
finish call_1
由此,我们可以看出,MyCallable_iAny2任务出现异常,从而将任务的关注点移到了MyCallable_iAny1任务,并不会打印出异常信息。如果,想打印出异常信息,需要这样写:
写法一:
try{ if(true){ throw new Exception("myException_B"); } }catch(Exception e){ e.printStackTrace();
}
运行结果:
java.lang.Exception: myException_B call_2 at myexecutorservice.MyCallable_iAny2.call(myinvokeAny.java:76) at myexecutorservice.MyCallable_iAny2.call(myinvokeAny.java:1)
这里获得了异常任务的结果,这是因为MyCallable_iAny2的异常状态未上报,这导致线程池认为其是正确的,从而未将关注点换到下一个任务
写法二:
try{ if(true){ throw new Exception("myException_B"); } }catch(Exception e){ // e.printStackTrace(); throw e; }
运行结果:
finish call_1
这里抛出了异常,从了线程池将关注点换到了下一个任务