What is the java equivalent of AggregateException

2020-03-01 07:09发布

In .net the AggregateException class allows you to throw an exception containing multiple exceptions.

For example, you would want to throw an AggregateException if you ran multiple tasks in parallel and some of them failed with exceptions.

Does java have an equivalent class?

The specific case I want to use it in:

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); 
}

4条回答
男人必须洒脱
2楼-- · 2020-03-01 07:38

I don't really see why you should use exceptions in the first place to mark tasks as incomplete/failed but in any case, it shouldn't be hard to create one yourself. Got any code to share so that we could help you with a more specific answer?

查看更多
我命由我不由天
3楼-- · 2020-03-01 07:40

I'm not aware of any built-in or library classes, as I've never even though of wanting to do this before (typically you would just chain the exceptions), but it wouldn't be that hard to write yourself.

You'd probably want to pick one of the Exceptions to be "primary" so it can be used to fill in stacktraces, etc.

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;
    }

}
查看更多
Bombasti
4楼-- · 2020-03-01 07:56

Java 7's Throwable.addSuppressed(Throwable) will do something similar, although it was built for a slightly different purpose (try-with-resource)

查看更多
我只想做你的唯一
5楼-- · 2020-03-01 07:59

You can represent multiple taska as

List<Callable<T>> tasks

Then if you want the computer to actually do them in parallel use

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

Now you can iterate through the results.

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
}

So realCause (if it exists) is whatever exception what thrown in its associated task.

查看更多
登录 后发表回答