如何捕获线程池执行产生的异常

1.如何捕获线程池执行产生的异常

就像例子1中所写的那样,executor执行一个Runnable接口,在Runnable的实现lambda表达式中try catch了异常之后,是没办法throw e往外抛出异常的。在main线程中想catch住线程池执行的异常,也catch不到。如果这样写是不行的,体会一下:

package com.test.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestThread {

    private static ExecutorService executor = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        try {
            CountDownLatch downLatch = new CountDownLatch(5);

            for (int i = 5; i >= 0; i--) {
                executor.submit(divide(i, downLatch));
            }

            downLatch.await();
        } catch (Exception e) {
            System.out.println("main出错了!" + e.getMessage());
            e.printStackTrace();
        }

        System.out.println("main运行结束了!");
        executor.shutdown();
    }

    private static Runnable divide(int a, CountDownLatch downLatch) {
        return () -> {
            try {
                int b = 100 / a;
                Thread.sleep(5000);
                System.out.println("a = " + a + " 算出b=" + b);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("divide出错了!");
            } finally {
                downLatch.countDown();
            }
        };
    }

}

 

所以改为executor.submit提交一个Callable带返回值的任务(Callable可以抛出异常),是否执行失败返回不同的值,submit提交返回future,然后检查返回值,如果失败,手动抛出异常

例子2:

package com.test.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestThread2 {

    private static ExecutorService executor = Executors.newFixedThreadPool(5);

    //线程执行成功
    private static final int THREAD_EXECUTE_OK = 1;

    //线程执行失败
    private static final int THREAD_EXECUTE_FAILED = 0;

    public static void main(String[] args) {
        try {
            CountDownLatch downLatch = new CountDownLatch(5);
            List<Future<Integer>> futureList = new ArrayList<>();

            for (int i = 5; i >= 0; i--) {
                Future<Integer> f = executor.submit(divide(i, downLatch));
                futureList.add(f);
            }

            System.out.println("各线程执行中...");
            downLatch.await();
            System.out.println("各线程执行完毕");

            //检查多线程是否有执行失败
            for (Future<Integer> future : futureList) {
                Integer state = future.get();

                if (THREAD_EXECUTE_FAILED == state) {
                    throw new RuntimeException("有线程执行失败!");
                }
            }
        } catch (Exception e) {
            System.out.println("main出错了!" + e.getMessage());
            e.printStackTrace();
        }

        System.out.println("main运行结束了!");
        executor.shutdown();
    }

    private static Callable<Integer> divide(int a, CountDownLatch downLatch) {
        return () -> {
            try {
                System.out.println("线程-" + Thread.currentThread() + "正在计算 100 / " + a);
                int b = 100 / a;
                Thread.sleep(5000);
                System.out.println("a = " + a + " 算出b=" + b + " 线程-" + Thread.currentThread() + "执行完毕");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("divide出错了!");
                return 0;
            } finally {
                downLatch.countDown();
            }

            return 1;
        };
    }

    /**
     * 检查多线程是否执行完毕
     */
    public boolean isTheadPoolDone(List<Future<?>> futureList) {
        boolean endFlag = true;

        if (null != futureList && futureList.size() > 0) {
            for (Future<?> future : futureList) {
                if (!future.isDone()) {
                    endFlag = false;
                    break;
                }
            }
        }
        return endFlag;
    }
}

console:

各线程执行中...
线程-Thread[pool-1-thread-5,5,main]正在计算 100 / 1
线程-Thread[pool-1-thread-4,5,main]正在计算 100 / 2
线程-Thread[pool-1-thread-1,5,main]正在计算 100 / 5
线程-Thread[pool-1-thread-3,5,main]正在计算 100 / 3
线程-Thread[pool-1-thread-2,5,main]正在计算 100 / 4
a = 2 算出b=50 线程-Thread[pool-1-thread-4,5,main]执行完毕
a = 1 算出b=100 线程-Thread[pool-1-thread-5,5,main]执行完毕
a = 4 算出b=25 线程-Thread[pool-1-thread-2,5,main]执行完毕
a = 3 算出b=33 线程-Thread[pool-1-thread-3,5,main]执行完毕
线程-Thread[pool-1-thread-5,5,main]正在计算 100 / 0
a = 5 算出b=20 线程-Thread[pool-1-thread-1,5,main]执行完毕
各线程执行完毕
divide出错了!
main出错了!有线程执行失败!
main运行结束了!
java.lang.ArithmeticException: / by zero
	at com.test.thread.TestThread2.lambda$divide$0(TestThread2.java:56)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException: 有线程执行失败!
	at com.test.thread.TestThread2.main(TestThread2.java:40)

Process finished with exit code 0

 

 

 

 

--

posted on 2024-11-03 16:31  有点懒惰的大青年  阅读(24)  评论(0编辑  收藏  举报