【并发编程】-ExecutorService的方法invokeAny与异常处理

69 阅读2分钟

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

ExecutorService的方法invokeAny与异常处理

运行类代码如下:

public class InvokeAnyRun {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new FCallable());
        list.add(new SCallable());
        ExecutorService executorService = Executors.newCachedThreadPool();
        try {
            String result = (String) executorService.invokeAny(list);
            System.out.println("已完成任务的返回值:"+result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

运行结果如下:

com.ozx.concurrentprogram.executor.service.SCallable 开始时间: 1660900886381

com.ozx.concurrentprogram.executor.service.FCallable 开始时间: 1660900886381

com.ozx.concurrentprogram.executor.service.SCallable 结束时间: 1660900886384

com.ozx.concurrentprogram.executor.service.FCallable 结束时间: 1660900886386

已完成任务的返回值:com.ozx.concurrentprogram.executor.service.SCallable

从运行结果看来虽然方法invokeAny()已经获取的第二个线程的返回值,但是第一个线程正在继续运行中,直到运行完毕。

修改运行类执行代码如下:

public class InvokeAnyRun {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new FCallable());
        list.add(new TCallable());
        ExecutorService executorService = Executors.newCachedThreadPool();
        try {
            String result = (String) executorService.invokeAny(list);
            System.out.println("已完成任务的返回值:"+result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

运行结果如下:

com.ozx.concurrentprogram.executor.service.TCallable 开始时间: 1660902186975

com.ozx.concurrentprogram.executor.service.FCallable 开始时间: 1660902186975

com.ozx.concurrentprogram.executor.service.FCallable 结束时间: 1660902186978

com.ozx.concurrentprogram.executor.service.TCallable 抛出异常中断......

已完成任务的返回值:com.ozx.concurrentprogram.executor.service.FCallable

从运行结果看出第一个线程执行完毕后,线程池将第三个线程设置为interrupt状态,而第三个线程可以自定义对中断interrupt状态进行处理,就是说可以决定是否使用Thread.currentThread().isInterrupted()结合throw new

InterruptedException()的代码。

如果使用Thread.currentThread().isInterrupted()结合throw new InterruptedException()的代码说明对第三个线程进行中断的意图更加明确。

方法InvokeAny()与执行慢的任务异常

执行时间短的任务优先执行完毕后,执行时间长的任务出现异常时,默认情况下不会在控制台输出异常信息,如果显式使用try-catch语句块则可以自定义捕获异常。