日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止

發布時間:2024/4/11 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。

歡迎跳轉到本文的原文鏈接:https://honeypps.com/java/java-multi-thread-of-uncaught-exception-handler/

當單線程的程序發生一個未捕獲的異常時我們可以采用try....catch進行異常的捕獲,但是在多線程環境中,線程拋出的異常是不能用try....catch捕獲的,這樣就有可能導致一些問題的出現,比如異常的時候無法回收一些系統資源,或者沒有關閉當前的連接等等。

首先來看一個示例:

?

package com.exception;public class NoCaughtThread {public static void main(String[] args){try{Thread thread = new Thread(new Task());thread.start();}catch (Exception e){System.out.println("==Exception: "+e.getMessage());}} }class Task implements Runnable {@Overridepublic void run(){System.out.println(3/2);System.out.println(3/0);System.out.println(3/1);} }

運行結果:

?

?

1 Exception in thread "Thread-0" java.lang.ArithmeticException: / by zeroat com.exception.Task.run(NoCaughtThread.java:25)at java.lang.Thread.run(Unknown Source)

可以看到在多線程中通過try....catch試圖捕獲線程的異常是不可取的。

?

Thread的run方法是不拋出任何檢查型異常的,但是它自身卻可能因為一個異常而被中止,導致這個線程的終結。
首先介紹一下如何在線程池內部構建一個工作者線程,如果任務拋出了一個未檢查異常,那么它將使線程終結,但會首先通知框架該現場已經終結。然后框架可能會用新的線程來代替這個工作線程,也可能不會,因為線程池正在關閉,或者當前已有足夠多的線程能滿足需要。當編寫一個向線程池提交任務的工作者類線程類時,或者調用不可信的外部代碼時(例如動態加載的插件),使用這些方法中的某一種可以避免某個編寫得糟糕的任務或插件不會影響調用它的整個線程。

package com.exception;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class InitiativeCaught {public void threadDeal(Runnable r, Throwable t){System.out.println("==Exception: "+t.getMessage());}class InitialtiveThread implements Runnable{@Overridepublic void run(){Throwable thrown = null;try{System.out.println(3/2);System.out.println(3/0);System.out.println(3/1);}catch(Throwable e){thrown =e;}finally{threadDeal(this,thrown);}}}public static void main(String[] args){ExecutorService exec = Executors.newCachedThreadPool();exec.execute(new InitiativeCaught().new InitialtiveThread());exec.shutdown();}}

運行結果:

?

?

1 ==Exception: / by zero

上面介紹了一種主動方法來解決未檢測異常。在Thread ApI中同樣提供了UncaughtExceptionHandle,它能檢測出某個由于未捕獲的異常而終結的情況。這兩種方法是互補的,通過將二者結合在一起,就能有效地防止線程泄露問題。

?

如下:

?

package com.exception;import java.lang.Thread.UncaughtExceptionHandler;public class WitchCaughtThread {public static void main(String args[]){Thread thread = new Thread(new Task());thread.setUncaughtExceptionHandler(new ExceptionHandler());thread.start();} }class ExceptionHandler implements UncaughtExceptionHandler {@Overridepublic void uncaughtException(Thread t, Throwable e){System.out.println("==Exception: "+e.getMessage());} }

運行結果:

?

?

1 ==Exception: / by zero

同樣可以為所有的Thread設置一個默認的UncaughtExceptionHandler,通過調用Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)方法,這是Thread的一個static方法。

?

如下:

?

package com.exception;import java.lang.Thread.UncaughtExceptionHandler;public class WitchCaughtThread {public static void main(String args[]){Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());Thread thread = new Thread(new Task());thread.start();} }class ExceptionHandler implements UncaughtExceptionHandler {@Overridepublic void uncaughtException(Thread t, Throwable e){System.out.println("==Exception: "+e.getMessage());} }

?

運行結果:

1 ==Exception: / by zero

?

如果采用線程池通過execute的方法去捕獲異常,先看下面的例子:

?

public class ExecuteCaught {public static void main(String[] args){ExecutorService exec = Executors.newCachedThreadPool();Thread thread = new Thread(new Task());thread.setUncaughtExceptionHandler(new ExceptionHandler());exec.execute(thread);exec.shutdown();} }

ExceptionHandler可參考上面的例子,運行結果:

?

?

1 Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zeroat com.exception.Task.run(NoCaughtThread.java:25)at java.lang.Thread.run(Unknown Source)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source)

可以看到并未捕獲到異常。

?

這時需要將異常的捕獲封裝到Runnable或者Callable中,如下所示:

package com.exception;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class ExecuteCaught {public static void main(String[] args){ExecutorService exec = Executors.newCachedThreadPool();exec.execute(new ThreadPoolTask());exec.shutdown();} }class ThreadPoolTask implements Runnable {@Overridepublic void run(){Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());System.out.println(3/2);System.out.println(3/0);System.out.println(3/1);} }

?

運行結果:

1 ==Exception: / by zero

只有通過execute提交的任務,才能將它拋出的異常交給UncaughtExceptionHandler,而通過submit提交的任務,無論是拋出的未檢測異常還是已檢查異常,都將被認為是任務返回狀態的一部分。如果一個由submit提交的任務由于拋出了異常而結束,那么這個異常將被Future.get封裝在ExecutionException中重新拋出。
下面兩個例子:

?

package com.exception;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class SubmitCaught {public static void main(String[] args){ExecutorService exec = Executors.newCachedThreadPool();exec.submit(new Task());exec.shutdown();} } package com.exception;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class SubmitCaught {public static void main(String[] args){ExecutorService exec = Executors.newCachedThreadPool();exec.submit(new ThreadPoolTask());exec.shutdown();} }

運行結果都是:

?

?

1

這樣可以證實我的觀點。接下來通過這個例子可以看到捕獲的異常:

package com.exception;import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future;public class SubmitCaught {public static void main(String[] args){ExecutorService exec = Executors.newCachedThreadPool();Future<?> future = exec.submit(new Task());exec.shutdown();try{future.get();}catch (InterruptedException | ExecutionException e){System.out.println("==Exception: "+e.getMessage());}} }

運行結果:

?

?

1 ==Exception: java.lang.ArithmeticException: / by zero

希望我整理的這些能夠給各位有所幫助。

?

歡迎跳轉到本文的原文鏈接:https://honeypps.com/java/java-multi-thread-of-uncaught-exception-handler/

歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。

總結

以上是生活随笔為你收集整理的JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。