面試官:線程池執(zhí)行過程中遇到異常會發(fā)生什么,怎樣處理?
線程遇到未處理的異常就結(jié)束了
這個好理解,當(dāng)線程出現(xiàn)未捕獲異常的時候就執(zhí)行不下去了,留給它的就是垃圾回收了。
線程池中線程頻繁出現(xiàn)未捕獲異常
?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{?????int?j?=?1/0;??});});?}}新建一個只有一個線程的線程池,每隔0.1s提交一個任務(wù),任務(wù)中是一個1/0的計算。Exception?in?thread?"customThread?0"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?1"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?2"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?3"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?4"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?5"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)可見每次執(zhí)行的線程都不一樣,之前的線程都沒有復(fù)用。原因是因為出現(xiàn)了未捕獲的異常。我們把異常捕獲試試:public?class?ThreadExecutor?{?private?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,???new?ArrayBlockingQueue<>(200),?new?ThreadFactoryBuilder().setNameFormat("customThread?%d").build());?@Test?public?void?test()?{??IntStream.rangeClosed(1,?5).forEach(i?->?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{????try?{?????int?j?=?1?/?0;????}?catch?(Exception?e)?{?????System.out.println(Thread.currentThread().getName()?+"?"+?e.getMessage());????}???});??});?}}customThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zero可見當(dāng)異常捕獲了,線程就可以復(fù)用了。" data-itemshowtype="0" tab="innerlink" data-linktype="2" data-darkmode-color-16340410061459="rgb(163, 163, 163)" data-darkmode-original-color-16340410061459="#fff|rgb(63, 63, 63)" wah-hotarea="click" hasload="1" style="outline: 0px; color: rgb(125, 144, 169); cursor: pointer; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;">public?class?ThreadExecutor?{
?private?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,
???new?ArrayBlockingQueue<>(200),?new?ThreadFactoryBuilder().setNameFormat("customThread?%d").build());
?@Test
?public?void?test()?{
??IntStream.rangeClosed(1,?5).forEach(i?->?{
???try?{
????Thread.sleep(100);
???}?catch?(InterruptedException?e)?{
????e.printStackTrace();
???}
???threadPoolExecutor.execute(()?->?{
?????int?j?=?1/0;
??});});
?}
}
?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{?????int?j?=?1/0;??});});?}}新建一個只有一個線程的線程池,每隔0.1s提交一個任務(wù),任務(wù)中是一個1/0的計算。Exception?in?thread?"customThread?0"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?1"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?2"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?3"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?4"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?5"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)可見每次執(zhí)行的線程都不一樣,之前的線程都沒有復(fù)用。原因是因為出現(xiàn)了未捕獲的異常。我們把異常捕獲試試:public?class?ThreadExecutor?{?private?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,???new?ArrayBlockingQueue<>(200),?new?ThreadFactoryBuilder().setNameFormat("customThread?%d").build());?@Test?public?void?test()?{??IntStream.rangeClosed(1,?5).forEach(i?->?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{????try?{?????int?j?=?1?/?0;????}?catch?(Exception?e)?{?????System.out.println(Thread.currentThread().getName()?+"?"+?e.getMessage());????}???});??});?}}customThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zero可見當(dāng)異常捕獲了,線程就可以復(fù)用了。" data-itemshowtype="0" tab="innerlink" data-linktype="2" data-darkmode-color-16340410061459="rgb(163, 163, 163)" data-darkmode-original-color-16340410061459="#fff|rgb(63, 63, 63)" wah-hotarea="click" hasload="1" style="outline: 0px; color: rgb(125, 144, 169); cursor: pointer; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;">Exception?in?thread?"customThread?0"?java.lang.ArithmeticException:?/?by?zero
?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)
?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
?at?java.lang.Thread.run(Thread.java:748)
Exception?in?thread?"customThread?1"?java.lang.ArithmeticException:?/?by?zero
?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)
?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
?at?java.lang.Thread.run(Thread.java:748)
Exception?in?thread?"customThread?2"?java.lang.ArithmeticException:?/?by?zero
?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)
?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
?at?java.lang.Thread.run(Thread.java:748)
Exception?in?thread?"customThread?3"?java.lang.ArithmeticException:?/?by?zero
?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)
?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
?at?java.lang.Thread.run(Thread.java:748)
Exception?in?thread?"customThread?4"?java.lang.ArithmeticException:?/?by?zero
?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)
?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
?at?java.lang.Thread.run(Thread.java:748)
Exception?in?thread?"customThread?5"?java.lang.ArithmeticException:?/?by?zero
?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)
?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
?at?java.lang.Thread.run(Thread.java:748)
?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{?????int?j?=?1/0;??});});?}}新建一個只有一個線程的線程池,每隔0.1s提交一個任務(wù),任務(wù)中是一個1/0的計算。Exception?in?thread?"customThread?0"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?1"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?2"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?3"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?4"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?5"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)可見每次執(zhí)行的線程都不一樣,之前的線程都沒有復(fù)用。原因是因為出現(xiàn)了未捕獲的異常。我們把異常捕獲試試:public?class?ThreadExecutor?{?private?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,???new?ArrayBlockingQueue<>(200),?new?ThreadFactoryBuilder().setNameFormat("customThread?%d").build());?@Test?public?void?test()?{??IntStream.rangeClosed(1,?5).forEach(i?->?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{????try?{?????int?j?=?1?/?0;????}?catch?(Exception?e)?{?????System.out.println(Thread.currentThread().getName()?+"?"+?e.getMessage());????}???});??});?}}customThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zero可見當(dāng)異常捕獲了,線程就可以復(fù)用了。" data-itemshowtype="0" tab="innerlink" data-linktype="2" data-darkmode-color-16340410061459="rgb(163, 163, 163)" data-darkmode-original-color-16340410061459="#fff|rgb(63, 63, 63)" wah-hotarea="click" hasload="1" style="outline: 0px; color: rgb(125, 144, 169); cursor: pointer; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;">public?class?ThreadExecutor?{
?private?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,
???new?ArrayBlockingQueue<>(200),?new?ThreadFactoryBuilder().setNameFormat("customThread?%d").build());
?@Test
?public?void?test()?{
??IntStream.rangeClosed(1,?5).forEach(i?->?{
???try?{
????Thread.sleep(100);
???}?catch?(InterruptedException?e)?{
????e.printStackTrace();
???}
???threadPoolExecutor.execute(()?->?{
????try?{
?????int?j?=?1?/?0;
????}?catch?(Exception?e)?{
?????System.out.println(Thread.currentThread().getName()?+"?"+?e.getMessage());
????}
???});
??});
?}
}
?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{?????int?j?=?1/0;??});});?}}新建一個只有一個線程的線程池,每隔0.1s提交一個任務(wù),任務(wù)中是一個1/0的計算。Exception?in?thread?"customThread?0"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?1"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?2"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?3"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?4"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)Exception?in?thread?"customThread?5"?java.lang.ArithmeticException:?/?by?zero?at?thread.ThreadExecutor.lambda$null$0(ThreadExecutor.java:25)?at?java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)?at?java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)?at?java.lang.Thread.run(Thread.java:748)可見每次執(zhí)行的線程都不一樣,之前的線程都沒有復(fù)用。原因是因為出現(xiàn)了未捕獲的異常。我們把異常捕獲試試:public?class?ThreadExecutor?{?private?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,???new?ArrayBlockingQueue<>(200),?new?ThreadFactoryBuilder().setNameFormat("customThread?%d").build());?@Test?public?void?test()?{??IntStream.rangeClosed(1,?5).forEach(i?->?{???try?{????Thread.sleep(100);???}?catch?(InterruptedException?e)?{????e.printStackTrace();???}???threadPoolExecutor.execute(()?->?{????try?{?????int?j?=?1?/?0;????}?catch?(Exception?e)?{?????System.out.println(Thread.currentThread().getName()?+"?"+?e.getMessage());????}???});??});?}}customThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zerocustomThread?0?/?by?zero可見當(dāng)異常捕獲了,線程就可以復(fù)用了。" data-itemshowtype="0" tab="innerlink" data-linktype="2" data-darkmode-color-16340410061459="rgb(163, 163, 163)" data-darkmode-original-color-16340410061459="#fff|rgb(63, 63, 63)" wah-hotarea="click" hasload="1" style="outline: 0px; color: rgb(125, 144, 169); cursor: pointer; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;">customThread?0?/?by?zero
customThread?0?/?by?zero
customThread?0?/?by?zero
customThread?0?/?by?zero
customThread?0?/?by?zero
問題來了,我們的代碼中異常不可能全部捕獲
如果要捕獲那些沒被業(yè)務(wù)代碼捕獲的異常,可以設(shè)置Thread類的uncaughtExceptionHandler屬性。這時使用ThreadFactoryBuilder會比較方便,ThreadFactoryBuilder是guava提供的ThreadFactory生成器。
new?ThreadFactoryBuilder()
.setNameFormat("customThread?%d")
.setUncaughtExceptionHandler((t,?e)?->?System.out.println(t.getName()?+?"發(fā)生異常"?+?e.getCause()))
.build()
修改之后:
public?class?ThreadExecutor?{
?private?static?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,
???new?ArrayBlockingQueue<>(200),
???new?ThreadFactoryBuilder()
?????.setNameFormat("customThread?%d")
?????.setUncaughtExceptionHandler((t,?e)?->?System.out.println("UncaughtExceptionHandler捕獲到:"?+?t.getName()?+?"發(fā)生異常"?+?e.getMessage()))
?????.build());
?@Test
?public?void?test()?{
??IntStream.rangeClosed(1,?5).forEach(i?->?{
???try?{
????Thread.sleep(100);
???}?catch?(InterruptedException?e)?{
????e.printStackTrace();
???}
???threadPoolExecutor.execute(()?->?{
????System.out.println("線程"?+?Thread.currentThread().getName()?+?"執(zhí)行");
????int?j?=?1?/?0;
???});
??});
?}
}
線程customThread?0執(zhí)行
UncaughtExceptionHandler捕獲到:customThread 0發(fā)生異常/ by zero
線程customThread?1執(zhí)行
UncaughtExceptionHandler捕獲到:customThread 1發(fā)生異常/ by zero
線程customThread?2執(zhí)行
UncaughtExceptionHandler捕獲到:customThread 2發(fā)生異常/ by zero
線程customThread?3執(zhí)行
UncaughtExceptionHandler捕獲到:customThread 3發(fā)生異常/ by zero
線程customThread?4執(zhí)行
UncaughtExceptionHandler捕獲到:customThread 4發(fā)生異常/ by zero
可見,結(jié)果并不是我們想象的那樣,線程池中原有的線程沒有復(fù)用!所以通過UncaughtExceptionHandler想將異常吞掉使線程復(fù)用這招貌似行不通。它只是做了一層異常的保底處理。
推薦一個 Spring Boot 基礎(chǔ)教程及實戰(zhàn)示例:https://www.javastack.cn/categories/Spring-Boot/
將excute改成submit試試
public?class?ThreadExecutor?{
?private?static?ThreadPoolExecutor?threadPoolExecutor?=?new?ThreadPoolExecutor(1,?1,?60,?TimeUnit.SECONDS,
???new?ArrayBlockingQueue<>(200),
???new?ThreadFactoryBuilder()
?????.setNameFormat("customThread?%d")
?????.setUncaughtExceptionHandler((t,?e)?->?System.out.println("UncaughtExceptionHandler捕獲到:"?+?t.getName()?+?"發(fā)生異常"?+?e.getMessage()))
?????.build());
?@Test
?public?void?test()?{
??IntStream.rangeClosed(1,?5).forEach(i?->?{
???try?{
????Thread.sleep(100);
???}?catch?(InterruptedException?e)?{
????e.printStackTrace();
???}
???Future>?future?=?threadPoolExecutor.submit(()?->?{
????System.out.println("線程"?+?Thread.currentThread().getName()?+?"執(zhí)行");
????int?j?=?1?/?0;
???});
???try?{
????future.get();
???}?catch?(InterruptedException?e)?{
????e.printStackTrace();
???}?catch?(ExecutionException?e)?{
????e.printStackTrace();
???}
??});
?}
}
線程customThread?0執(zhí)行
java.util.concurrent.ExecutionException:?java.lang.ArithmeticException:?/?by?zero
線程customThread?0執(zhí)行
java.util.concurrent.ExecutionException:?java.lang.ArithmeticException:?/?by?zero
線程customThread?0執(zhí)行
java.util.concurrent.ExecutionException:?java.lang.ArithmeticException:?/?by?zero
線程customThread?0執(zhí)行
java.util.concurrent.ExecutionException:?java.lang.ArithmeticException:?/?by?zero
線程customThread?0執(zhí)行
java.util.concurrent.ExecutionException:?java.lang.ArithmeticException:?/?by?zero
通過submit提交線程可以屏蔽線程中產(chǎn)生的異常,達(dá)到線程復(fù)用。當(dāng)get()執(zhí)行結(jié)果時異常才會拋出。
原因是通過submit提交的線程,當(dāng)發(fā)生異常時,會將異常保存,待future.get();時才會拋出。最新面試題整理好了,點(diǎn)擊Java面試庫小程序在線刷題。
這是Futuretask的部分run()方法,看setException:
public?void?run()?{
????try?{
????????Callable?c?=?callable;
????????if?(c?!=?null?&&?state?==?NEW)?{
????????????V?result;
????????????boolean?ran;
????????????try?{
????????????????result?=?c.call();
????????????????ran?=?true;
????????????}?catch?(Throwable?ex)?{
????????????????result?=?null;
????????????????ran?=?false;
????????????????setException(ex);
????????????}
????????????if?(ran)
????????????????set(result);
????????}
????}?
}
protected?void?setException(Throwable?t)?{
????if?(UNSAFE.compareAndSwapInt(this,?stateOffset,?NEW,?COMPLETING))?{
????????outcome?=?t;
????????UNSAFE.putOrderedInt(this,?stateOffset,?EXCEPTIONAL);?//?final?state
????????finishCompletion();
????}
}
public?V?get()?throws?InterruptedException,?ExecutionException?{
????int?s?=?state;
????if?(s?<=?COMPLETING)
????????s?=?awaitDone(false,?0L);
????return?report(s);
}
private?V?report(int?s)?throws?ExecutionException?{
????Object?x?=?outcome;
????if?(s?==?NORMAL)
????????return?(V)x;
????if?(s?>=?CANCELLED)
????????throw?new?CancellationException();
????throw?new?ExecutionException((Throwable)x);
}
總結(jié)
本文鏈接:https://blog.csdn.net/weixin_37968613/article/details/108407774
歡迎關(guān)注“Java引導(dǎo)者”,我們分享最有價值的Java的干貨文章,助力您成為有思想的Java開發(fā)工程師!
評論
圖片
表情
