Java 如果其中一个线程抛出异常,如何停止所有正在运行的线程?

Java 如果其中一个线程抛出异常,如何停止所有正在运行的线程?,java,multithreading,Java,Multithreading,在我的一个应用程序中,我使用ExecutorService类创建一个固定线程池,并CountDownLatch等待线程完成。如果进程没有抛出任何异常,那么这可以正常工作。如果在任何线程中发生异常,我需要停止所有正在运行的线程,并向主线程报告错误。谁能帮我解决这个问题 这是我用于执行多个线程的示例代码 private void executeThreads() { int noOfThreads = 10; ExecutorService execu

在我的一个应用程序中,我使用
ExecutorService
类创建一个固定线程池,并
CountDownLatch
等待线程完成。如果进程没有抛出任何异常,那么这可以正常工作。如果在任何线程中发生异常,我需要停止所有正在运行的线程,并向主线程报告错误。谁能帮我解决这个问题

这是我用于执行多个线程的示例代码

    private void executeThreads()
    {
        int noOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(noOfThreads);     
        try      
       {
        CountDownLatch latch = new CountDownLatch(noOfThreads);
        for(int i=0; i< noOfThreads; i++){
         executor.submit(new ThreadExecutor(latch));
        }
        latch.await();           
       }
       catch(Exception e)
       {
        e.printStackTrace();
       }
       finally
       {
        executor.shutDown();
       }
   }
private void executeThreads()
{
int noOfThreads=10;
ExecutorService executor=Executors.newFixedThreadPool(noOfThreads);
尝试
{
CountDownLatch闩锁=新的CountDownLatch(noOfThreads);
for(inti=0;i
这是Executor类

     public class ThreadExecutor implements Callable<String> {
        CountDownLatch latch ;
        public ThreadExecutor(CountDownLatch latch){
            this.latch = latch;
        }   

    @Override
    public String call() throws Exception
    {
        doMyTask(); // process logic goes here!
        this.latch.countDown();
        return "Success";
    }
公共类ThreadExecutor实现可调用{
倒计时闩锁;
公共线程执行器(倒计时闩锁){
this.latch=闩锁;
}   
@凌驾
公共字符串调用()引发异常
{
doMyTask();//进程逻辑在这里!
这个.latch.countDown();
返回“成功”;
}
=============================================================================

谢谢大家:)

我已经纠正了我的课,如下所示,这是现在的工作

private void executeThreads()
    {
        int noOfThreads = 10;
        ExecutorService executor = Executors.newFixedThreadPool(noOfThreads);     
       ArrayList<Future<Object>> futureList = new ArrayList<Future<Object>>(noOfThreads );
    try
    {
        userContext = BSF.getMyContext();
        CountDownLatch latch = new CountDownLatch(noOfComponentsToImport);

        for(ImportContent artifact:artifactList){
            futureList.add(executor.submit(new ThreadExecutor(latch)));
        }

        latch.await();

        for(Future<Object> future : futureList)
        {
                  try
                  {
                      future.get();                 
                   }
                   catch(ExecutionException e)
                   {   //handle it               
                    }
        }           

    }
    catch (Exception e) {
       //handle it
    }
    finally
    {
        executor.shutdown();      

        try
        {
            executor.awaitTermination(90000, TimeUnit.MILLISECONDS);
        }
        catch (InterruptedException e)
        {
           //handle it
        }
    }
   }
private void executeThreads()
{
int noOfThreads=10;
ExecutorService executor=Executors.newFixedThreadPool(noOfThreads);
ArrayList futureList=新的ArrayList(noOfThreads);
尝试
{
userContext=BSF.getMyContext();
CountDownLatch latch=新的CountDownLatch(noOfComponentsToImport);
for(导入内容工件:工件列表){
添加(executor.submit(新线程执行器(闩锁));
}
satch.wait();
for(未来:未来列表)
{
尝试
{
future.get();
}
捕获(执行例外)
{//处理它
}
}           
}
捕获(例外e){
//处理它
}
最后
{
executor.shutdown();
尝试
{
执行器等待终止(90000,时间单位毫秒);
}
捕捉(中断异常e)
{
//处理它
}
}
}
执行者类别:

public class ThreadExecutor implements Callable<String> {
        private static volatile boolean isAnyError;
        CountDownLatch latch ;
        public ThreadExecutor(CountDownLatch latch){
            this.latch = latch;
        }   

    @Override
    public String call() throws Exception
    {

      try{
            if(!isAnyError)
            { 
               doMyTask(); // process logic goes here!
            }
     }
     catch(Exception e)
     {
        isAnyError = true ;
        throw e;
      }
      finally
      {
        this.latch.countDown();
       }
        return "Success";
    }
公共类ThreadExecutor实现可调用{
私有静态易失性布尔isAnyError;
倒计时闩锁;
公共线程执行器(倒计时闩锁){
this.latch=闩锁;
}   
@凌驾
公共字符串调用()引发异常
{
试一试{
如果(!isAnyError)
{ 
doMyTask();//进程逻辑在这里!
}
}
捕获(例外e)
{
isAnyError=true;
投掷e;
}
最后
{
这个.latch.countDown();
}
返回“成功”;
}

我强烈建议您使用一个健壮的机制来倒计时闩锁。使用一个包罗万象的
尝试最后{latch.countDown();}
使用一个单独的机制检测线程中的错误。

我认为您还需要一个线程,称之为“观察者”,它将检查
AtomicBoolean
的值是否为
true
。设置后,您将关闭主执行服务。请记住,关闭机制不能保证立即停止所有线程。请阅读以下内容,例如:

我认为您需要重新构造代码。查看

执行给定任务,返回已执行任务的结果 成功完成(即未引发异常),如果有 正常或异常返回时,未完成的任务 已取消。如果给定 此操作正在进行时,集合被修改


这似乎是您需要的行为。而且您不需要
倒计时闩锁
,因为
main
将在
invokeAny
中阻塞,请使用
ExecutorCompletionService
,并在任务持续时间之外完成
ExecutorService
(即,之后不会关闭):


由于任务1失败,任务2被取消。

+1-是的,我总是从任何具有这种结构的线程代码开始,这样线程在没有通知“something”的情况下就无法逃逸。因此建议调用waittermination()作为一个解决方案?但是如何计算等待的时间?它似乎会返回第一个成功的。如果我想要所有成功的结果呢?谢谢。您需要添加executor.shutdownNow();executor.waitTermination(long.MAX_值,TimeUnit.NANOSECONDS);完全关闭它这个循环做什么?while(futuresIt.hasNext()){if(futuresIt.next().isDone()){futuresIt.remove();}else{complete=false;}}@devel这是在遍历集合时从集合中移除项的标准方法
completionService.take().get()
blocks,这是不好的。是的,你应该为你的所有web应用程序使用一个线程池。我认为上面的代码有问题。如果所有代码都没有异常执行,completionService.take()将等待服务器
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

class Threader {

    static ExecutorService service = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        new Threader().start();
        service.shutdown();
    }

    private void start() {
        CompletionService<Void> completionService = new ExecutorCompletionService<Void>(
                service);
        /*
         * Holds all the futures for the submitted tasks
         */
        List<Future<Void>> results = new ArrayList<Future<Void>>();

        for (int i = 0; i < 3; i++) {
            final int callableNumber = i;

            results.add(completionService.submit(new Callable<Void>() {

                                                     @Override
                                                     public Void call() throws Exception {
                                                         System.out.println("Task " + callableNumber
                                                                 + " in progress");
                                                         try {
                                                             Thread.sleep(callableNumber * 1000);
                                                         } catch (InterruptedException ex) {
                                                             System.out.println("Task " + callableNumber
                                                                     + " cancelled");
                                                             return null;
                                                         }
                                                         if (callableNumber == 1) {
                                                             throw new Exception("Wrong answer for task "
                                                                     + callableNumber);
                                                         }
                                                         System.out.println("Task " + callableNumber + " complete");
                                                         return null;
                                                     }
                                                 }

            ));
        }

        boolean complete = false;
        while (!complete) {
            complete = true;
            Iterator<Future<Void>> futuresIt = results.iterator();
            while (futuresIt.hasNext()) {
                if (futuresIt.next().isDone()) {
                    futuresIt.remove();
                } else {
                    complete = false;
                }
            }

            if (!results.isEmpty()) {
                try {
                /*
                 * Examine results of next completed task
                 */
                    completionService.take().get();
                } catch (InterruptedException e) {
                /*
                 * Give up - interrupted.
                 */
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                } catch (ExecutionException e) {
                /*
                 * The task threw an exception
                 */
                    System.out.println("Execution exception " + e.getMessage());
                    complete = true;
                    for (Future<Void> future : results) {
                        if (!future.isDone()) {
                            System.out.println("Cancelling " + future);
                            future.cancel(true);
                        }
                    }
                }
            }
        }

    }
}
Task 0 in progress
Task 2 in progress
Task 1 in progress
Task 0 complete
Execution exception java.lang.Exception: Wrong answer for task 1
Cancelling java.util.concurrent.FutureTask@a59698
Task 2 cancelled