Java多線程——<七>多線程的異常捕捉

來源:互聯網
上載者:User

標籤:

一、概述

  為什麼要單獨講多線程的異常捕捉呢?先看個例子:

public class ThreadException implements Runnable{    @Override    public void run() {        throw new RuntimeException();    }    //現象:控制台列印出異常資訊,並運行一段時間後才停止    public static void main(String[] args){        //就算把線程的執行語句放到try-catch塊中也無濟於事        try{            ExecutorService exec = Executors.newCachedThreadPool();            exec.execute(new ThreadException());        }catch(RuntimeException e){            System.out.println("Exception has been handled!");        }    }}

  在run中手動拋出了一個運行時異常,在main中啟動線程,catch語句塊中捕捉下異常,捕捉到列印一句話。運行結果如:

  發現異常被拋到了控制台,沒有列印catch塊中的語句。

  結論:多線程運行不能按照順序執行過程中捕獲異常的方式來處理異常,異常會被直接拋出到控制台(由於線程的本質,使得你不能捕獲從線程中逃逸的異常。一旦異常逃逸出任務的run方法,它就會向外傳播到控制台,除非你採用特殊的形式捕獲這種異常。),這樣會讓你很頭疼,無法捕捉到異常就無法處理異常而引發的問題。

  於是,我們一定會想如何在多線程中捕捉異常呢?

二、多線程中捕捉異常

  我們來按照下面的步驟完成這次實驗:

  1.定義異常處理器

   要求,實現 Thread.UncaughtExceptionHandler的uncaughtException方法,如下:

/* * 第一步:定義符合線程異常處理器規範的“異常處理器” * 實現Thread.UncaughtExceptionHandler規範 */class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{    /*     * Thread.UncaughtExceptionHandler.uncaughtException()會線上程因未捕獲的異常而臨近死亡時被調用     */    @Override    public void uncaughtException(Thread t, Throwable e) {        System.out.println("caught    "+e);    }}

 

  2.定義使用該異常處理器的線程工廠

/* * 第二步:定義線程工廠 * 線程工廠用來將任務附著給線程,並給該線程綁定一個異常處理器 */class HanlderThreadFactory implements ThreadFactory{    @Override    public Thread newThread(Runnable r) {        System.out.println(this+"creating new Thread");        Thread t = new Thread(r);        System.out.println("created "+t);        t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());//設定線程工廠的異常處理器        System.out.println("eh="+t.getUncaughtExceptionHandler());        return t;    }}

  3.定義一個任務,讓其拋出一個異常

/* * 第三步:我們的任務可能會拋出異常 * 顯示的拋出一個exception */class ExceptionThread implements Runnable{    @Override    public void run() {        Thread t = Thread.currentThread();        System.out.println("run() by "+t);        System.out.println("eh = "+t.getUncaughtExceptionHandler());        throw new RuntimeException();    }}

  4.調用實驗

/* * 第四步:使用線程工廠建立線程池,並調用其execute方法 */public class ThreadExceptionUncaughtExceptionHandler{    public static void main(String[] args){        ExecutorService exec = Executors.newCachedThreadPool(new HanlderThreadFactory());        exec.execute(new ExceptionThread());    }}

  運行結果如:

三、結論

  在java中要捕捉多線程產生的異常,需要自訂異常處理器,並設定到對應的線程工廠中(即第一步和第二步)。

四、拓展

  如果你知道將要在代碼中處處使用相同的異常處理器,那麼更簡單的方式是在Thread類中設定一個靜態域,並將這個處理器設定為預設的未捕獲處理器。

這個處理器只有在不存線上程專有的未捕獲異常處理器的情況下才會被調用。

public static void main(String[] args){        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());        ExecutorService exec =Executors.newCachedThreadPool();        exec.execute(new ExceptionThread());}

註:以上代碼均來自《thinking in java》,內容均是自己總結,如有錯誤,歡迎大家批評指正

 

Java多線程——<七>多線程的異常捕捉

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.