我正在使用invokeAll()调用线程列表。只有当所有线程完成其任务时,AFAIK invokeAll()才会返回。
ExecutorService threadExecutor = Executors.newFixedThreadPool(getThreadSize());
List<Future<Object>> future = w_threadExecutor.invokeAll(threadList);
当所有线程完成时调用
for (Future<Object> w_inProgressThread : w_future)
{
//
它会停止发生异常的线程而不是剩余的线程。 有没有办法在任何线程抛出异常时停止所有其他线程? 或者我必须提交每个任务而不是invokeAll()??
我尝试在invokeAll()上使用invokeAny(),但不会取消剩余的任务 invokeAny():如果其中一个任务完成(或抛出异常),其余的Callable将被取消。 参考: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:
正如waltersu所建议我试过
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");
发生异常时不会停止
答案 0 :(得分:3)
您必须逐个提交(),而不是 invokeAll(),然后检查 Future 是否有异常。
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 :(回答操作的更新1问题)
那是因为你的任务有一个长循环,不会检查中断,这使你的任务不可取消。那你怎么阻止它?我认为您必须修改其他任务以使其可取消。正如the official doc所说:
如果一个线程长时间没有调用抛出InterruptedException的方法怎么办?然后它必须定期调用Thread.interrupted,如果收到中断,则返回true。例如:
for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}
如果您不想修改任务并希望快速停止,该怎么办?有一种方法可以阻止非可扩展的线程。它是 Thread.stop()。但是,首先,您无法在不使用反射的情况下从线程池获取线程。此外,它被弃用了,因为&#34;它本质上是不安全的&#34;根据{{3}}。
所以,最好的做法(我认为)是检查你的任务(或部分代码)的中断,这是不可取消的,并且花费很长时间才能完成。
答案 1 :(得分:0)
for(Future<Object> fut : future){
try {
System.out.println(fut.get());
}
catch (InterruptedException | ExecutionException e) {
Thread.currentThread().interrupt();
// or notify all here
}
答案 2 :(得分:0)
你可以调用Wrappers来获取你的work-runnables以及对它们将被调用的Executor的引用。例外,您可以在run()中立即关闭。
class ExceptionHandlingWrapper implements Runnable{
private ExecutorService es;
private Runnable childRunnable;
// CTOR taking an ExecutorService and a Runnable
public ExceptionHandlingWrapper ( ExecutorService es, Runnable work ){
this.es = es;
this.childRunnable = work;
}
@Override public void run(){
try{
childRunnable.run();
}
catch(Exception ex){
// Todo: LOG IT!
es.shutdownNow();
}
}
}
当然,这也适用于Callables。
答案 3 :(得分:0)
很少有建议:
invokeAll
并将所有任务提交至ExecutorService
。shutdown
&amp; shutdownNow
正如这些问题中所述:How to stop next thread from running in a ScheduledThreadPoolExecutor