返回博主主页

afterExecute进行异常处理,但是注意! 这个也只适用于excute提交,因为submit的task.run里面把异常吞了

线程池异常处理详解,一文搞懂! - 小推爱学习 - 博客园

点击查看代码
final void runWorker(Worker w) {
//当前线程
        Thread wt = Thread.currentThread();
        //我们的提交的任务
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) {
                w.lock();
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                    //直接就调用了task的run方法 
                        task.run(); //如果是futuretask的run,里面是吞掉了异常,不会有异常抛出,
                       // 因此Throwable thrown = null;  也不会进入到catch里面
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                    //调用线程池的afterExecute方法 传入了task和异常
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

FutureTask 执行记录异常在 outcome,通过future.get()可以把异常读出来

image
image

private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;

image
image

验证 submit 吞了异常

public static void main(String[] args) {
        Thread t = new Thread(() -> {
            int a = 0;
            int b = 1;
            System.out.println("begin");
            int c = b / a; // divide by zero
            System.out.println("end");
        });
        t.setUncaughtExceptionHandler((t1, e) -> {
            System.out.println("Thread.setUncaughtExceptionHandler\t" + e);  // 不生效,因为 submit(t) 接收的是Runnable对象,最终jdk会把 Runnable 包装为 Thread 执行。外部传入一个 Thread 对象虽然设置了 setUncaughtExceptionHandler,不起作用
        });
        ExecutorService a = pool();
        a.submit(t); // submit 不会抛出异常
    }

    public static ExecutorService pool() {
        // 创建线程池
        final int corePoolSize = 2;
        final int maximumPoolSize = 64;
        final long keepAliveTime = 60L;
        TimeUnit timeUnit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(100);
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("pool")
            // .setUncaughtExceptionHandler(
            //     (t1, e) ->{
            //         System.out.println("ThreadFactory.setUncaughtExceptionHandler\t"+e);
            //     }
            //     )
            .build();
        RejectedExecutionHandler rejectedExecutionHandler = (r, executor) -> {
            System.out.println("abort");
        };
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, blockingQueue,
            threadFactory, rejectedExecutionHandler){
            // @Override
            // protected void afterExecute(Runnable r, Throwable t) {
            //     super.afterExecute(r, t);
            //     System.out.println("afterExecute\t"+t);
            // }
        };
    }

输出:

begin

execute 提交

public static void main(String[] args) {
        Thread t = new Thread(() -> {
            int a = 0;
            int b = 1;
            System.out.println("begin");
            int c = b / a; // divide by zero
            System.out.println("end");
        });
        t.setUncaughtExceptionHandler((t1, e) -> {
            System.out.println("Thread.setUncaughtExceptionHandler\t" + e);
        });
        ExecutorService a = pool();
        a.execute(t);
    }

    public static ExecutorService pool() {
        // 创建线程池
        final int corePoolSize = 2;
        final int maximumPoolSize = 64;
        final long keepAliveTime = 60L;
        TimeUnit timeUnit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(100);
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("pool")
            // .setUncaughtExceptionHandler(
            //     (t1, e) ->{
            //         System.out.println("ThreadFactory.setUncaughtExceptionHandler\t"+e);
            //     }
            //     )
            .build();
        RejectedExecutionHandler rejectedExecutionHandler = (r, executor) -> {
            System.out.println("abort");
        };
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, blockingQueue,
            threadFactory, rejectedExecutionHandler){
            // @Override
            // protected void afterExecute(Runnable r, Throwable t) {
            //     super.afterExecute(r, t);
            //     System.out.println("afterExecute\t"+t);
            // }
        };
    }

输出:

begin
Exception in thread "pool" java.lang.ArithmeticException: / by zero
at com.huawei.wim.app.service.ZipTest.lambda$main\(0(ZipTest.java:56) at java.lang.Thread.run(Thread.java:748) 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)

异常顺序

使用了 afterExecute,还是可以爆出异常

 public static void main(String[] args) {
        Runnable t = () -> {
            int a = 0;
            int b = 1;
            System.out.println("begin");
            int c = b / a; // divide by zero
            System.out.println("end");
        };
        ExecutorService a = pool();
        a.execute(t);
    }

    public static ExecutorService pool() {
        // 创建线程池
        final int corePoolSize = 2;
        final int maximumPoolSize = 64;
        final long keepAliveTime = 60L;
        TimeUnit timeUnit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(100);
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("pool")
            // .setUncaughtExceptionHandler(
            //     (t1, e) ->{
            //         System.out.println("ThreadFactory.setUncaughtExceptionHandler\t"+e);
            //     }
            //     )
            .build();
        RejectedExecutionHandler rejectedExecutionHandler = (r, executor) -> {
            System.out.println("abort");
        };
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, blockingQueue,
            threadFactory, rejectedExecutionHandler){
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                System.out.println("afterExecute\t"+t);
            }
        };
    }

输出:

begin
afterExecute java.lang.ArithmeticException: / by zero
Exception in thread "pool" java.lang.ArithmeticException: / by zero
at com.huawei.wim.app.service.ZipTest.lambda$main\(0(ZipTest.java:56) 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)

afterExecute + setUncatchExeceptionHandler

 public static void main(String[] args) {
        Runnable t = () -> {
            int a = 0;
            int b = 1;
            System.out.println("begin");
            int c = b / a; // divide by zero
            System.out.println("end");
        };
        ExecutorService a = pool();
        a.execute(t);
    }

    public static ExecutorService pool() {
        // 创建线程池
        final int corePoolSize = 2;
        final int maximumPoolSize = 64;
        final long keepAliveTime = 60L;
        TimeUnit timeUnit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(100);
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("pool")
            .setUncaughtExceptionHandler(
                (t1, e) ->{
                    System.out.println("ThreadFactory.setUncaughtExceptionHandler\t"+e);
                }
                )
            .build();
        RejectedExecutionHandler rejectedExecutionHandler = (r, executor) -> {
            System.out.println("abort");
        };
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, blockingQueue,
            threadFactory, rejectedExecutionHandler){
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                System.out.println("afterExecute\t"+t);
            }
        };
    }

输出:

begin
afterExecute java.lang.ArithmeticException: / by zero
ThreadFactory.setUncaughtExceptionHandler java.lang.ArithmeticException: / by zero

posted @ 2024-09-20 16:36  懒惰的星期六  阅读(20)  评论(0编辑  收藏  举报

Welcome to here

主页