【并发编程】- 线程池使用ExecutorCompletionService与异常处理(二)

80 阅读2分钟

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

ExecutorCompletionService类与异常(二)

修改运行类代码如下:

public class ExceptionCallableRun {
    public static void main(String[] args) {
        ExceptionFirstCallable firstCallable = new ExceptionFirstCallable();
        ExceptionSecondCallable secondCallable = new ExceptionSecondCallable();

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        ExecutorCompletionService executorCompletionService = new ExecutorCompletionService(executorService);
        executorCompletionService.submit(firstCallable);
        executorCompletionService.submit(secondCallable);


        for (int i = 0; i < 2 ; i++) {
                System.out.println("移除已完成任务:"+executorCompletionService.poll());
        }
        try {
            Thread.sleep(8000);
            System.out.println("第一个线程: "+executorCompletionService.poll());
            System.out.println("第二个线程: "+executorCompletionService.poll());
            System.out.println("主线程结束!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

移除已完成任务:null 移除已完成任务:null com.ozx.concurrentprogram.executor.service.ExceptionFirstCallable 线程执行开始时间:1660724969482 com.ozx.concurrentprogram.executor.service.ExceptionFirstCallable 线程执行结束时间:1660724973493 com.ozx.concurrentprogram.executor.service.ExceptionSecondCallable 线程执行开始时间:1660724973494 第一个线程: java.util.concurrent.FutureTask@3ecf72fd 第二个线程: null 主线程结束!

从运行结果看出第一个任务休眠时间比较少,开始使用poll()方法并没有移除已完成的任务,两个任务都处在休眠中,经过一段休眠时间后,再次使用poll()方法能移除第一个任务,而第二个任务因为发生异常,没能输出返回值,并没有被poll()方法移除,而第一个任务被poll()方法移除直接输出FutureTask对象。

使用poll().get()方法获取任务对应的返回值

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

public class ExceptionCallableRun {
    public static void main(String[] args) {
        ExceptionFirstCallable firstCallable = new ExceptionFirstCallable();
        ExceptionSecondCallable secondCallable = new ExceptionSecondCallable();

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        ExecutorCompletionService executorCompletionService = new ExecutorCompletionService(executorService);
        executorCompletionService.submit(firstCallable);
        executorCompletionService.submit(secondCallable);


        for (int i = 0; i < 2 ; i++) {
                System.out.println("移除已完成任务:"+executorCompletionService.poll());
        }
        try {
            Thread.sleep(8000);
            System.out.println("第一个线程: "+executorCompletionService.poll().get());
            System.out.println("第二个线程: "+executorCompletionService.poll().get());
            System.out.println("主线程结束!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

移除已完成任务:null 移除已完成任务:null com.ozx.concurrentprogram.executor.service.ExceptionFirstCallable 线程执行开始时间:1660725526232 com.ozx.concurrentprogram.executor.service.ExceptionFirstCallable 线程执行结束时间:1660725530248 com.ozx.concurrentprogram.executor.service.ExceptionSecondCallable 线程执行开始时间:1660725530249 第一个线程: com.ozx.concurrentprogram.executor.service.ExceptionFirstCallable Exception in thread "main" java.lang.NullPointerException at com.ozx.concurrentprogram.executor.controller.ExceptionCallableRun.main(ExceptionCallableRun.java:39)

从运行结果看出第一个任务完成后,调用poll().get()方法能获取任务对应的返回值,第二个任务出现异常后,调用poll().get()方法直接返回任务中异常信息。