以下SSCCE显示从服务器获取记录(比如说)。 ExecutorService
用于创建2个线程的ThreadPool
,我调用了所有这些线程的Timeout
为3秒。
故意我做了一些失败的任务。
现在我的问题是,如何让EmpID的任务失败?
MainClass:
public class MultiThreadEx {
public static void main(String[] args) {
String[] empIDArray = {
"100", "200", "300", "400", "500",
"600", "700", "800", "900", "1000",
"1100", "1200", "1300", "1400", "1500"
};
List<ThreadTaskEach> taskList = new ArrayList<ThreadTaskEach>();
try {
for(String empID : empIDArray) {
taskList.add(new ThreadTaskEach(empID));
}
} catch(Exception e) {
System.out.println("Exception occured: " + e.getMessage());
}
List<Future<Map<String, String>>> futureList = null;
try {
ExecutorService service = Executors.newFixedThreadPool(2);
futureList = service.invokeAll(taskList, 3, TimeUnit.SECONDS);
service.shutdown();
} catch(InterruptedException ie) {
System.out.println("Exception occured: " + ie.getMessage());
}
for(Future<Map<String, String>> future : futureList) {
try {
Map<String, String> resultMap = future.get();
for(String key : resultMap.keySet()) {
System.out.println(resultMap.get(key));
}
} catch(ExecutionException ee) {
System.out.println("Exception occured: " + ee.getMessage());
} catch (InterruptedException ie) {
System.out.println("Exception occured: " + ie.getMessage());
} catch(CancellationException e) {
System.out.println("Exception occured: " + e.getMessage());
}
}
}
}
线程类
class ThreadTaskEach implements Callable<Map<String, String>>{
private String empID;
public ThreadTaskEach(String empID) {
this.empID = empID;
}
@Override
public Map<String, String> call() throws Exception {
try {
return prepareMap(empID);
} catch(Exception e) {
System.out.println("Exception occured: " + e.getMessage());
throw new Exception("Exception occured: " + e.getMessage());
}
}
private Map<String, String> prepareMap(String empID) throws InterruptedException {
Map<String, String> map = new HashMap<String, String>();
if(Integer.parseInt(empID) % 500 == 0) {
Thread.sleep(5000);
}
map.put(empID, empID + ": " + Thread.currentThread().getId());
return map;
}
}
在上面的代码500中,1000 ..无法在3秒内完成。
Map<String, String> resultMap = future.get();
所以,当我为这些任务说future.get()时,我得到了CancellationException
。但是如何从任务中获得EmpID?
答案 0 :(得分:6)
您可以逐个invokeAll
每个任务,而不是使用submit
,并将每个未来存储在地图中:
Future<?> f = executor.submit(task);
map.put(f, task.getId());
现在当你试图获得时,如果你有异常,你可以使用地图返回到id。但是,您需要在每个future.get()
上设置超时,这可能对您的用例不实用。
另一种方法是使用invokeAll
which guarantees to return the futures in the same order as the tasks that were submitted的规范。
返回表示任务的Futures列表,按照与给定任务列表的迭代器生成的顺序相同的顺序。
只要您使用List,迭代顺序就固定了,您可以匹配两个列表:
for (int i = 0; i < futureList.size(); i++) {
Future<Map<String, String>> future = futureList.get(i)
try {
Map<String, String> resultMap = future.get();
for(String key : resultMap.keySet()) {
System.out.println(resultMap.get(key));
}
} catch(ExecutionException ee) {
System.out.println("Exception in task " + taskList.get(i).getId());
}
}
请确保使用具有稳定迭代顺序的集合(ArrayList很好)。