多線程下運行時異常的捕獲-UncaughtExceptionHandler

當一個線程因爲未捕獲的異常而退出時,JVM會將這個異常交給UncaughtExceptionHandler(異常處理器)來處理,如何沒有設置異常處理器,會將異常信息輸出到System.err。多線程環境下,其他線程仍然在輸出日誌,System.err輸出的異常信息很可能被忽略。可以通過設置UncaughtExceptionHandler,將未捕獲的異常信息保存到指定的日誌文件中。

1.首先實現Thread.UncaughtExceptionHandler接口

package com.yuanyk.uncaughtExceptionHandler;

public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("thread-->"+t.getName()+" get uncCatchException:"+e.getMessage());
    }
}

2.測試Thread.start()

    private static void testThread(){
        Thread t = new Thread(() -> {
            int i = 1/0;
        });
        t.setName("test thread");
        t.start();
    }

此時沒有設置UncaughtExceptionHandler,運行結果如下:

添加異常處理器後:

    private static void testThread(){
        Thread t = new Thread(() -> {
            int i = 1/0;
        });
        t.setName("test thread");
        t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        t.start();
    }

3.測試線程池的execute()

需要在線程池的構造方法中傳入ThreadFactory,在ThreadFactory.newThread(Runnable r)方法中設置異常處理器

    private static void testExector(){
        ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactory() {
            AtomicInteger index = new AtomicInteger(0);
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, " thread-"+index.incrementAndGet());
                thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
                return thread;
            }
        });
        executor.execute(() -> {int i = 1/0;});
        executor.execute(() -> {int i = 1/0;});
        executor.shutdown();
    }

運行結果

4.測試線程池的submit()

    private static void testSubmit(){
        ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactory() {
            AtomicInteger index = new AtomicInteger(0);
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, " thread-"+index.incrementAndGet());
                thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
                return thread;
            }
        });
        Future<String> future = executor.submit(() -> {return 1/0+"";});
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }

 

總結:Thread.start()和ExecutorService.executr()方法可以通過設置UncaughtExceptionHandler處理未捕獲的異常。ExecutorService.submit()方法提交任務,這個任務拋出的異常被Future.get封裝在ExecutionException中重新拋出,設置的UncaughtExceptionHandler並無作用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章