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

153 阅读1分钟

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

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(secondCallable);
        executorCompletionService.submit(firstCallable);



        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.ExceptionSecondCallable 线程执行开始时间:1660726435173 Exception in thread "main" java.lang.NullPointerException at com.ozx.concurrentprogram.executor.controller.ExceptionCallableRun.main(ExceptionCallableRun.java:39) com.ozx.concurrentprogram.executor.service.ExceptionFirstCallable 线程执行开始时间:1660726445178 com.ozx.concurrentprogram.executor.service.ExceptionFirstCallable 线程执行结束时间:1660726449190

丛运行结果看来第二个任务先执行,第二个任务执行发生异常,调用poll().get()方法直接抛出异常信息,第一个任务执行后并未输出任务的返回值。

CompletionService的submit(Runnable runnable,V result)的使用

实体类代码如下:

@Data
public class User {
    private String username;
    private String password;
}

线程执行代码如下:

public class ThirdRunnable implements Runnable {

    private User user;

    public ThirdRunnable(User user){
        super();
        this.user=user;
    }

    @Override
    public void run() {
        user.setUsername("Gxin");
        user.setPassword("20220819");
        System.out.println(super.getClass().getName()+"运行了");
    }

}

运行类执行代码如下:

public class CompletionServiceRun {
    public static void main(String[] args) {
        User user = new User();
        ThirdRunnable thirdRunnable = new ThirdRunnable(user);
        ExecutorService executorService = Executors.newCachedThreadPool();
        ExecutorCompletionService completionService = new ExecutorCompletionService(executorService);
        Future<User> future = completionService.submit(thirdRunnable, user);
        try {
            System.out.println("账号:"+future.get().getUsername() +" 密码:"+future.get().getPassword());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

com.ozx.concurrentprogram.executor.service.ThirdRunnable运行了

账号:Gxin 密码:20220819

接口CompletionService完全可以避免FutureTask类的阻塞的缺点,可更加有效处理Future的返回结果,就是说哪个任务先执行完,CompletionService就会先获取这个任务的返回值再接着往下处理。