3

我正在调用使用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()而不是cancell剩余的任务 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

threadExecutor.notifyAll()中断所有线程 –

+0

@AkashLodha ''从'Object'中的notifyAll()'唤醒在这个对象的监视器上等待的所有线程“。线程不在任何特定对象的显示器上等待,是吗?我错过了什么? – davmac

+0

我假设threadList是想要在同一个对象上锁定的线程。 –

回答

0
不会停止
+0

如果一个任务以异常退出,invokeAll仍然等待所有任务完成。 – waltersu

+0

你..我已经改变了答案 –

0

您可以调用包含您的工作可执行文件的引导程序,并引用它们将要调用的执行程序。例外情况下,您可以在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

你必须提交()一个接一个,而不是的invokeAll(),然后检查未来有例外。

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题)

那是因为你的任务有很长的环路,它不检查中断,这使得你的任务不可取消。那么你如何阻止它?我认为你必须修改你的其他任务以使它们可以被取消。由于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()。但是,首先,如果不使用反射,您无法从线程池中获取线程。此外,根据javadoc,因“根本上不安全”而不推荐使用。因此,最佳实践(我认为)是检查你的任务(或代码的一部分)的中断,这是无法解决的,需要很长时间才能完成。

+0

请检查我更新的问题。 – happy

+0

更新:如果所有任务都成功完成,仍然需要调用threadExecutor.shutdown()以便应用程序可以存在。因为http://stackoverflow.com/a/20057584/4493265 – waltersu

+0

请检查我的更新1:在问题..如果发生异常ut不会终止其他线程 – happy