【实战总结】线程池异常处理策略

简单谈谈线程池在使用过程中出现异常的一些处理策略,合理使用线程池,必须能够识别主线程与线程池直接的关系、充分了解线程池机制,发挥优点,了解盲区,合理利用不留坑。

先demo几个例子,有时间展开论述下使用场景和异常处理。

/**
 * created by guanjian on 2020/6/18 15:30
 */
public class ThreadPoolExecutorTest extends BaseTest {
 
    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
 
    @Test
    public void execute() {
        System.out.println("BEGIN-execute");
 
        IntStream.range(0, 10).forEach(x ->
                taskExecutor.execute(() -> {
                            //子线程异常抛出,不会阻塞主线程,而且可以立刻看到异常
                            throw new RuntimeException("error");
                        }
                )
        );
 
        System.out.println("END-execute");
    }
 
    @Test
    public void execute_countDownLatch() {
        System.out.println("BEGIN-execute-countDownLatch");
 
        final CountDownLatch cdl = new CountDownLatch(10);
 
        IntStream.rangeClosed(0, 10).forEach(x ->
                taskExecutor.execute(() -> {
                            try {
                                throw new RuntimeException("error");
                            } finally {
                                //如果使用多线程处理,必须用finally处理cdl.countDown(),以免子线程处理异常
                                cdl.countDown();
                            }
                        }
                )
        );
 
        try {
            //阻塞主线程,直到线程池处理完毕或超时
            cdl.await(5, TimeUnit.SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        System.out.println("END-execute-countDownLatch");
    }
 
    @Test
    public void submit() {
        System.out.println("BEGIN-submit-unfutureGet");
 
        IntStream.range(0, 10).forEach(x ->
                taskExecutor.submit(() -> {
                            //submit使用future进行处理,异常会存储在临时变量中,触发异常抛出需要调用future.get()
                            //这里没有进行future.get()调用,出现异常会存在临时变量中不会抛出而是被“吞掉”,好处是不影响并行的其他线程任务,不好是永远不知道是否异常
                            throw new RuntimeException("error");
                        }
                )
        );
 
        System.out.println("END-submit-unfutureGet");
    }
 
 
    @Test
    public void submit_futureGetException() {
        System.out.println("BEGIN-submit-futureGet");
 
        IntStream.range(0, 10).forEach(x -> {
                    Future future = taskExecutor.submit(() -> {
                                //submit使用future进行处理,异常会存储在临时变量中,触发异常抛出需要调用future.get()
                                throw new RuntimeException("error");
                            }
                    );
                    try {
                        future.get();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
        );
 
        System.out.println("END-submit-futureGet");
    }
}

 

你可能感兴趣的:(实战总结)