问题描述
我正在使用invokeAll()来调用线程列表. AFAIK invokeAll()仅在所有线程完成其任务时返回.
I am invoking List of threads using invokeAll(). AFAIK invokeAll() will return only when all the threads completes its task.
ExecutorService threadExecutor = Executors.newFixedThreadPool(getThreadSize());
List<Future<Object>> future = w_threadExecutor.invokeAll(threadList);
当所有线程完成时被调用
this is called when all threads finishes
for (Future<Object> w_inProgressThread : w_future)
{
//
它停止发生异常的线程,而不停止发生异常的线程.如果任何一个线程抛出异常,是否有一种方法可以停止所有其他线程?还是我必须提交每个任务而不是invokeAll()??
It stops the thread in which exception occured and not the remaining one.Is there a way to stop all the other threads if any of the thread throws exception?Or do I have to submit each task instead of invokeAll()??
我尝试在invokeAll()上使用invokeAny(),但是无法取消剩余的任务invokeAny():如果其中一项任务完成(或引发异常),则其余的Callable被取消.参考: http://tutorials.jenkov.com/java-util-concurrent/executorservice .html
I tried using invokeAny() instead on invokeAll() but does not cancell remaining taskinvokeAny() : If one of the tasks complete (or throws an exception), the rest of the Callable's are cancelled.Ref : http://tutorials.jenkov.com/java-util-concurrent/executorservice.html
更新:
CompletionService<Object> completionService = new ExecutorCompletionService<Object>(w_threadExecutor);
List<Future<Object>> futures = new ArrayList<Future<Object>>();
for(Thread w_mt : threadList)
{
futures.add(completionService.submit(w_mt));
}
for (int numTaken = 0; numTaken < futures.size(); numTaken++) {
Future f = completionService.take();
try {
Object result = f.get();
System.out.println(result); // do something with the normal result
} catch (Exception e) {
System.out.println("Catched ExecutionException, shutdown now!");
//threadExecutor.shutdownNow();
Thread.currentThread().interrupt();
for (Future<Object> inProgressThread : futures)
{
inProgressThread.cancel(true);
}
break;
}
更新1:
按照沃尔特苏的建议,我尝试过
As suggested by waltersu I tried
ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
CompletionService<Object> completionService = new ExecutorCompletionService<Object>(threadExecutor);
List<Future<Object>> futures = new ArrayList<Future<Object>>();
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
String s=null;
// Thread.sleep(1000);
for(int i=0; i < 1000000; i++){
int j =10 ;
if(i==100)
{
s.toString();
}
System.out.println("dazfczdsa :: " + i);
}
//throw new Exception("This is an expected Exception");
return s;
}
}));
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
for(int i=0; i < 1000000; i++){
int j =0 ;
j= j+2;
System.out.println("dasa :: " + i);
}
Thread.sleep(3000);
return "My First Result";
}
}));
while (futures.size() > 0) {
Future f = completionService.take();
futures.remove(f);
try {
Object result = f.get();
System.out.println(result); // do something with the normal result
} catch (ExecutionException e) {
System.out.println("Caught exception from one task: " + e.getCause().getMessage() + ". shutdown now!");
f.cancel(true);
threadExecutor.shutdownNow();
break;
}
}
System.out.println("Main exists");
这不会在发生异常时停止
this does not stop when exception occurs
推荐答案
您必须一个一个地 submit(),而不是 invokeAll(),然后检查是否未来具有异常.
You have to submit() one by one, instead of invokeAll(), then check if the Future has Exception.
public static void main(String[] args) throws InterruptedException {
ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
CompletionService<Object> completionService = new ExecutorCompletionService<>(threadExecutor);
List<Future<Object>> futures = new ArrayList<>();
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
Thread.sleep(1000);
throw new Exception("This is an expected Exception");
}
}));
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
Thread.sleep(3000);
return "My First Result";
}
}));
while (futures.size() > 0) {
Future f = completionService.take();
futures.remove(f);
try {
Object result = f.get();
System.out.println(result); // do something with the normal result
} catch (ExecutionException e) {
System.out.println("Caught exception from one task: " + e.getCause().getMessage() + ". shutdown now!");
threadExecutor.shutdownNow();
break;
}
}
System.out.println("Main exists");
}
更新1 :(回答op的更新1问题)
Update 1: (To answer op's update 1 question)
这是因为您的任务有一个较长的循环,无法检查中断,这使您的任务无法取消.那你怎么制止它呢?我认为您必须修改其他任务才能将其取消.正如官方文档所述:
That's because your task has a long loop which doesn't check the interruption, which makes your task noncancelable. Then how do you stop it? I think you have to modify your other tasks to make them cancelable. As the official doc says:
for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}
如果您不想修改任务又希望它迅速停止怎么办?有一种方法可以停止不可取消的线程.这是 Thread.stop().但是,首先,如果不使用反射,就无法从线程池中获取线程.此外,不赞成使用它,因为根据 javadoc .
What if you don't want to modify your task and also want it to stop quickly? There's a method you can stop a noncancelable thread. It's Thread.stop(). But, at first, you can't get the thread from threadpool without using reflection. Besides, it's deprecated because "it is inherently unsafe" according to the javadoc.
因此,最佳实践(我认为)是检查任务(或代码的一部分)中的中断,这既不可取消又要花费很长时间才能完成.
So, the best practice(I think) is to check the interruption in your task(or part of code) which is both noncancelable and spending a long time to finish.
这篇关于如果线程列表中的任何线程发生异常,则中断所有线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!