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
这里抛出了异常,从了线程池将关注点换到了下一个任务
ExecutorService的invokeAny方法的更多相关文章
- ExecutorService的invokeAny方法注意
package com.msxf.datasource.thirdpart.service.extface; import java.util.HashSet; import java.util.Li ...
- ExecutorService的submit方法使用
在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动.调度.管理线程的一大堆API了.在Java5以后,通过Executor来启动线程比用Thread的start()更好.在新特征中 ...
- ExecutorService的submit方法的坑
先看一段代码: public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerExcept ...
- ExecutorService
接口 java.util.concurrent.ExecutorService 表述了异步执行的机制,并且可以让任务在后台执行.壹個 ExecutorService 实例因此特别像壹個线程池.事实上, ...
- Java并发编程核心方法与框架-ExecutorService的使用
在ThreadPoolExecutor中使用ExecutorService中的方法 方法invokeAny()和invokeAll()具有阻塞特性 方法invokeAny()取得第一个完成任务的结果值 ...
- ExecutorService.invokeAny()和ExecutorService.invokeAll()的使用剖析
ExecutorService是JDK并发工具包提供的一个核心接口,相当于一个线程池,提供执行任务和管理生命周期的方法.ExecutorService接口中的大部分API都是比较容易上手使用的,本文主 ...
- [翻译][Java]ExecutorService的正确关闭方法
https://blog.csdn.net/zaozi/article/details/38854561 https://blog.csdn.net/z69183787/article/details ...
- 线程池 多线程运行结束后 如何关闭? ExecutorService的正确关闭方法
前言 最近在使用ExecutorService的时候,对于与ExecutorService相关的概念有些迷糊, 加上本身ExecutorService内部的有些方法名在取名上也容易让使用者误解,导致 ...
- ExecutorService的execute和submit方法
三个区别: 1.接收的参数不一样 2.submit有返回值,而execute没有 Method submit extends base method Executor.execute by creat ...
随机推荐
- PHP7 关于变量的基本判断
刚学 PHP ,一些基础还不太牢固,边实践边记录. about NULL $class_name = null; 语句结束后,$class_name 是空,没有,什么都没有的“空”.用 is_null ...
- mysql 命令连接
远程登陆MySQL,同时指定对应的端口和ip. 假设远程的ip为:10.154.0.43 端口为:1341 输入如下命令: mysql -h 10.154.0.43 -P 1341 -u root - ...
- POJ1475 Pushing Boxes 华丽丽的双重BFS
woc累死了写了两个半小时...就是BFS?我太菜了... 刚开始以为让人预先跑一遍BFS,然后一会儿取两节加起来就好了,结果发现求出来的最短路(就是这个意思)会因箱子的移动而变化....我死了QWQ ...
- Python-删除列表中重复元素的方法
1.set()方法 x = [1,2,3,4,5,1] y = list(set(x)) print(y) ``` [1, 2, 3, 4, 5] ``` 2. x = ['b','c','d','b ...
- 字典序的第K小数字
今天zyb参加一场面试,面试官听说zyb是ACMer之后立马抛出了一道算法题给zyb:有一个序列,是1到n的一种排列,排列的顺序是字典序小的在前,那么第k个数字是什么?例如n=15,k=7, 排列顺序 ...
- webstrom 搭建 nodejs
1.安装好 nodejs .下载地址 http://nodejs.org/#download,一路next,位置自己定,直到完成. 2.安装好 webstorm.官网下载,破解方法很多,自己搜吧. 3 ...
- UVA - 10780 唯一分解定理
白书P171 对m,n!分解,质因子指数取min #include<iostream> #include<algorithm> #include<cstdio> # ...
- Oracle 常用函数大全
Oracle 11g 常用函数(Functions)详解 目录 ABS. 3 ACOS. 3 ADD_MONTHS. 4 ASCII 4 ASCIISTR. 5 ASIN.. 5 ATAN.. 5 A ...
- 方格填数--蓝桥杯---dfs
答案:1580 相似题目:N皇后问题 注意要枚举的是什么 #include<iostream> #include<string.h> using namespace std; ...
- java将文本写入本地硬盘
注意:首先要在E盘创建qaz.txt文本文件.然后执行代码写入. public static void main(String[] args) { SecurityCodeUtils scu = ne ...