最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Java子線程中的異常處理方法(通用)

 更新時(shí)間:2017年09月26日 08:23:27   作者:Java小伙伴  
下面小編就為大家?guī)?lái)一篇基于Java子線程中的異常處理方法(通用)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

在普通的單線程程序中,捕獲異常只需要通過(guò)try ... catch ... finally ...代碼塊就可以了。那么,在并發(fā)情況下,比如在父線程中啟動(dòng)了子線程,如何在父線程中捕獲來(lái)自子線程的異常,從而進(jìn)行相應(yīng)的處理呢?

常見(jiàn)錯(cuò)誤

也許有人會(huì)覺(jué)得,很簡(jiǎn)單嘛,直接在父線程啟動(dòng)子線程的地方try ... catch一把就可以了,其實(shí)這是不對(duì)的。

原因分析

讓我們回憶一下Runnable接口的run方法的完整簽名,因?yàn)闆](méi)有標(biāo)識(shí)throws語(yǔ)句,所以方法是不會(huì)拋出checked異常的。至于RuntimeException這樣的unchecked異常,由于新線程由JVM進(jìn)行調(diào)度執(zhí)行,如果發(fā)生了異常,也不會(huì)通知到父線程。

public abstract void run()

解決辦法

那么,如何在父線程中捕獲來(lái)自子線程的異常呢?樓主想到了3種常用方法,分享給大家。

方法一:子線程中try... catch...

最簡(jiǎn)單有效的辦法,就是在子線程的方法中,把可能發(fā)生異常的地方,用try ... catch ... 語(yǔ)句包起來(lái)。子線程代碼:

public class ChildThread implements Runnable {
 public void run() {
  doSomething1();
  try {
   // 可能發(fā)生異常的方法
   exceptionMethod();
  } catch (Exception e) {
   // 處理異常
   System.out.println(String.format("handle exception in child thread. %s", e));
  }
  doSomething2();
 }
}

方法二:為線程設(shè)置異常處理器UncaughtExceptionHandler

為線程設(shè)置異常處理器。具體做法可以是以下幾種:

(1)Thread.setUncaughtExceptionHandler設(shè)置當(dāng)前線程的異常處理器

(2)Thread.setDefaultUncaughtExceptionHandler為整個(gè)程序設(shè)置默認(rèn)的異常處理器如果當(dāng)前線程有異常處理器(默認(rèn)沒(méi)有),則優(yōu)先使用該UncaughtExceptionHandler類(lèi);否則,如果當(dāng)前線程所屬的線程組有異常處理器,則使用線程組的ExceptionHandler;否則,使用全局默認(rèn)的DefaultUncaughtExceptionHandler;如果都沒(méi)有的話,子線程就會(huì)退出。

注意:子線程中發(fā)生了異常,如果沒(méi)有任何類(lèi)來(lái)接手處理的話,是會(huì)直接退出的,而不會(huì)留下打印任何日志。所以,如果什么都不做的話,是會(huì)出現(xiàn)子線程任務(wù)既沒(méi)執(zhí)行,也沒(méi)有任何日志提示的“詭異”現(xiàn)象的。

設(shè)置當(dāng)前線程的異常處理器:

public class ChildThread implements Runnable { 
 private static ChildThreadExceptionHandler exceptionHandler;

 static {
  exceptionHandler = new ChildThreadExceptionHandler();
 }

 public void run() {
  Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
  System.out.println("do something 1");
  exceptionMethod();
  System.out.println("do something 2");
 }

 public static class ChildThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
  public void uncaughtException(Thread t, Throwable e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  }
 }
}

或者,設(shè)置所有線程的默認(rèn)異常處理器

public class ChildThread implements Runnable {
 private static ChildThreadExceptionHandler exceptionHandler;

 static {
  exceptionHandler = new ChildThreadExceptionHandler();
  Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
 }

 public void run() {
  System.out.println("do something 1");
  exceptionMethod();
  System.out.println("do something 2");
 }

 private void exceptionMethod() {
  throw new RuntimeException("ChildThread exception");
 }

 public static class ChildThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
  public void uncaughtException(Thread t, Throwable e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  }
 }
}

命令行輸出:do something 1

handle exception in child thread. java.lang.RuntimeException: ChildThread exception

方法三,通過(guò)Future的get方法捕獲異常

使用線程池提交一個(gè)能獲取到返回信息的方法,也就是ExecutorService.submit(Callable)在submit之后可以獲得一個(gè)線程執(zhí)行結(jié)果的Future對(duì)象,而如果子線程中發(fā)生了異常,通過(guò)future.get()獲取返回值時(shí),可以捕獲到ExecutionException異常,從而知道子線程中發(fā)生了異常。

子線程代碼:

public class ChildThread implements Callable {
 public Object call() throws Exception {
  System.out.println("do something 1");
  exceptionMethod();
  System.out.println("do something 2");
  return null;
 }

 private void exceptionMethod() {
  throw new RuntimeException("ChildThread1 exception");
 }
}

父線程代碼:

public class Main {
 public static void main(String[] args) {
  ExecutorService executorService = Executors.newFixedThreadPool(8);
  Future future = executorService.submit(new ChildThread());
  try {
   future.get();
  } catch (InterruptedException e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  } catch (ExecutionException e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  } finally {
   if (executorService != null) {
    executorService.shutdown();
   }
  }
 }
}

命令行輸出:do something 1

handle exception in child thread. java.util.concurrent.ExecutionException: java.lang.RuntimeException: ChildThread1 exception

總結(jié)

上面就是3種常用的Java子線程異常處理方法。其實(shí)樓主還想到了另外幾個(gè)特定場(chǎng)景下的解決辦法,改天再分析,謝謝大家支持~

這篇基于Java子線程中的異常處理方法(通用)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

大姚县| 乌审旗| 江门市| 静宁县| 清水县| 泾源县| 南宁市| 洪湖市| 伽师县| 金门县| 沅陵县| 屯门区| 台前县| 封丘县| 四川省| 城固县| 勐海县| 贵南县| 漾濞| 章丘市| 龙州县| 巴南区| 宁化县| 瓦房店市| 崇信县| 措勤县| 玛沁县| 仁寿县| 新乡市| 高淳县| 屯留县| 三原县| 新邵县| 台东县| 蕲春县| 南昌市| 盐山县| 永昌县| 彭阳县| 饶阳县| 政和县|