private<T> T doInvokeAny(Collection<?extendsCallable<T>> tasks,boolean timed,long nanos)throws InterruptedException, ExecutionException, TimeoutException {//1.参数校验if(tasks == null)thrownewNullPointerException();int ntasks = tasks.size();if(ntasks ==0)thrownewIllegalArgumentException();//2.保存结果,这里用到了CompletionService,CompletionService可以让我们按照任务的完成顺序,优先//获取到已经完成的任务的结果,具体可阅读参考文章
ArrayList<Future<T>> futures =newArrayList<Future<T>>(ntasks);
ExecutorCompletionService<T> ecs =newExecutorCompletionService<T>(this);// For efficiency, especially in executors with limited// parallelism, check to see if previously submitted tasks are// done before submitting more of them. This interleaving// plus the exception mechanics account for messiness of main// loop.try{// Record exceptions so that if we fail to obtain any result, we can throw the last exception we got.//3.记录异常和超时时间,如果获取结果异常就把最后的一个异常抛出
ExecutionException ee = null;finallong deadline = timed ? System.nanoTime()+ nanos :0L;
Iterator<?extendsCallable<T>> it = tasks.iterator();// Start one task for sure; the rest incrementally//4.启动一个任务,任务数减一,活跃数置为1
futures.add(ecs.submit(it.next()));--ntasks;int active =1;//5.循环中处理,直到返回或者breakfor(;;){//6.尝试获取第一个任务的结果(如果结果队列是空的就会返回null)
Future<T> f = ecs.poll();if(f == null){//7.如果没有获取到,说明前一个任务还未完成,并且判断还有任务,那么就再执行下一个任务if(ntasks >0){--ntasks;
futures.add(ecs.submit(it.next()));++active;}//8.到这说明没有活跃任务,说明通过循环所有的任务都在执行中了,就breakelseif(active ==0)break;//9.到这里说明任务结果也没拿到,也没有剩余任务了,那就只能等正在执行的任务结果了,并且是超时模式,需要考虑超时时间,超时了就抛出异常elseif(timed){
f = ecs.poll(nanos, TimeUnit.NANOSECONDS);if(f == null)thrownewTimeoutException();
nanos = deadline - System.nanoTime();}//10.这里和前一个逻辑一样,但是不需要考虑超时,阻塞等待结果take是阻塞的,为空就会等待,前面的poll不会阻塞,这里会一直//等到一个结果,然后下一次循环就可以在下面的if逻辑中返回了else
f = ecs.take();}if(f != null){//11.如果获取到了,就返回这个结果--active;try{return f.get();}catch(ExecutionException eex){
ee = eex;}catch(RuntimeException rex){
ee =newExecutionException(rex);}}}//12.出现了异常就抛出异常if(ee == null)
ee =newExecutionException();throw ee;}finally{//13.取消其余任务for(int i =0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);}}
publicclassInvokeAnyTimedTest{publicstaticvoidmain(String[] args)throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Callable<String>> list =newArrayList<>();for(int i =1; i <10; i++){
list.add(newMyTask(i +""));}
String result = null;try{
result = executorService.invokeAny(list,100, TimeUnit.MILLISECONDS);}catch(TimeoutException e){
System.err.println(e.getClass());
e.printStackTrace();}
System.out.println(result);
executorService.shutdown();}//省略...}//异常打印,超时时间设置为100msclassjava.util.concurrent.TimeoutException
java.util.concurrent.TimeoutException
at java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:184)
at java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:225)
at com.intellif.mozping.threadpool.invokeany.InvokeAnyTimedTest.main(InvokeAnyTimedTest.java:25)
null