Java中与.net的AggregateException相对应的是什么?

22
在.net中,AggregateException类允许您抛出一个包含多个异常的异常。
例如,如果您并行运行多个任务并且其中一些任务失败,则应抛出AggregateException。
Java是否有等效的类?
我想使用它的具体情况:
public static void runMultipleThenJoin(Runnable... jobs) {
    final List<Exception> errors = new Vector<Exception>();
    try {
        //create exception-handling thread jobs for each job
        List<Thread> threads = new ArrayList<Thread>();
        for (final Runnable job : jobs)
            threads.add(new Thread(new Runnable() {public void run() {
                try {
                    job.run();
                } catch (Exception ex) {
                    errors.add(ex);
                }
            }}));

        //start all
        for (Thread t : threads)
            t.start();

        //join all
        for (Thread t : threads)
            t.join();            
    } catch (InterruptedException ex) {
        //no way to recover from this situation
        throw new RuntimeException(ex);
    }

    if (errors.size() > 0)
        throw new AggregateException(errors); 
}

我不清楚是否有这样的东西。不过,我也从来没有去寻找过。 - Powerlord
4个回答

12

6

我不知道是否有任何内置的或库类与此相关,因为我以前从未想过要这样做(通常您只需链接异常),但自己编写也不难。

您可能希望选择其中一个异常作为“主要”异常,以便用于填充堆栈跟踪等。

public class AggregateException extends Exception {

    private final Exception[] secondaryExceptions;

    public AggregateException(String message, Exception primary, Exception... others) {
        super(message, primary);
        this.secondaryExceptions = others == null ? new Exception[0] : others;
    }

    public Throwable[] getAllExceptions() {

        int start = 0;
        int size = secondaryExceptions.length;
        final Throwable primary = getCause();
        if (primary != null) {
            start = 1;
            size++;
        }

        Throwable[] all = new Exception[size];

        if (primary != null) {
            all[0] = primary;
        }

        Arrays.fill(all, start, all.length, secondaryExceptions);
        return all;
    }

}

1
你可以将多个任务表示为:
List<Callable<T>> tasks

如果你想让计算机真正并行执行它们,请使用

ExecutorService executorService = .. initialize executor Service
List<Future<T>> results = executorService.invokeAll ( ) ;

现在您可以遍历结果。
try
{
     T val = result . get ( ) ;
}
catch ( InterruptedException cause )
{
     // this is not the exception you are looking for
}
catch ( ExecutionExeception cause )
{
     Throwable realCause = cause . getCause ( ) // this is the exception you are looking for
}

因此,realCause(如果存在)就是与其关联任务中抛出的任何异常。


1
很高兴看到已经有了并发运行任务的方法。但是,你的解决方案没有处理代表多个任务失败的异常。 - Craig Gidney

0

我真的不明白为什么你要使用异常来标记任务未完成/失败,但无论如何,自己创建一个异常应该不难。你有任何代码可以分享吗?这样我们就可以帮助你得到更具体的答案。


1
我不是用它来“标记”任何东西,我只是想指示至少一个失败。我编辑了主贴以包含代码。 - Craig Gidney
2
一个例子是在验证方面非常有用。不要在第一个无效属性上抛出异常,而是验证整个类,这样消费者就可以理解为什么有效负载无效。这是发现API的更好方式。 - Brandon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接