【并发编程】- ExecutorService的方法invokeAny与全部任务发生异常处理

135 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

方法InvokeAny()与执行时间短的任务异常

如果想捕获空指针异常使用显式try-catch的方式进行捕获就可以,但在第二个线程中的catch块中如果不重新throw抛出异常,那么主线程不能取得第二个线程任务的返回值,而取得的是第一个线程的返回值,因为第一个线程的异常状态并未上报,导致线程池认为第一个线程运行状态是正确的,而未发现第一个线程是一个异常的任务,也就是并未使关注点换到下一个任务,如果第二个线程将异常再次抛出,那么线程池认为第二个线程出现了异常,那么将关注点切换到第一个线程,获取第一个线程的结果值输出。

第二个线程执行关键代码如下:

public class SCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        try{
            System.out.println(super.getClass().getName()+" 开始时间: "+System.currentTimeMillis());
            for (int i = 0; i < 2345 ; i++) {
                Math.random();
                Math.random();
                Math.random();
            }
            if(true){
                System.out.println(super.getClass().getName()+"线程中断了....");
                throw new NullPointerException();
            }
            System.out.println(super.getClass().getName()+" 结束时间: "+System.currentTimeMillis());
        }catch(Exception e){
            e.printStackTrace();
            System.out.println(super.getClass().getName()+" 通过显式try-catch捕获异常了,异常原因: "+e.getMessage());
            throw e;
        }
        return super.getClass().getName();
    }
}

方法InvokeAny()与全部异常

在全部任务都出现异常时,应用会抛出ExecutionException异常。

第一个线程执行代码如下:

public class FCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println(super.getClass().getName()+"  开始时间:  "+System.currentTimeMillis());
        for (int i = 0; i < 1234 ; i++) {
            Math.random();
            Math.random();
            Math.random();
        }
        System.out.println(super.getClass().getName()+"  结束时间:  "+System.currentTimeMillis());
        if(true){
            System.out.println("创建异常");
            throw new Exception(super.getClass().getName()+"线程报错了");
        }
        return super.getClass().getName();
    }
}

第二个线程执行代码如下:

public class SCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
            System.out.println(super.getClass().getName()+" 开始时间: "+System.currentTimeMillis());
            for (int i = 0; i < 123456 ; i++) {
                Math.random();
                Math.random();
                Math.random();
            }
            if(true){
                System.out.println(super.getClass().getName()+"线程中断了....");
                throw new Exception(super.getClass().getName()+"线程报错了");
            }
            System.out.println(super.getClass().getName()+" 结束时间: "+System.currentTimeMillis());
        return super.getClass().getName();
    }
}