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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

java异常_Java线程池「异常处理」正确姿势:有病就得治

發(fā)布時(shí)間:2024/9/27 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java异常_Java线程池「异常处理」正确姿势:有病就得治 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

假設(shè)我們有一個(gè)線程池,由于程序需要,我們向該線程池中提交了好多好多任務(wù),但是 這些任務(wù)都沒(méi)有對(duì)異常進(jìn)行try catch處理,并且運(yùn)行的時(shí)候都拋出了異常 。這會(huì)對(duì)線程池的運(yùn)行帶來(lái)什么影響?

正確答案是:沒(méi)有影響。這可不是好事情。

想一下,如果是你開(kāi)發(fā)了一個(gè)線程池供開(kāi)發(fā)者使用,你會(huì)不會(huì)對(duì)這種情況做處理?想想也是肯定的,不然你提供給別人使用的東西就是有問(wèn)題的,欠考慮的。而且java線程池的主要開(kāi)發(fā)人員是大名鼎鼎的Doug Lea,你覺(jué)得他開(kāi)發(fā)的代碼怎么會(huì)允許出現(xiàn)這種問(wèn)題?

這個(gè)問(wèn)題很棘手,因?yàn)樗稍诮锹淅?#xff0c;程序正常運(yùn)行的時(shí)候,它并不會(huì)出來(lái)作祟。

問(wèn)題分析

接下來(lái)我們來(lái)看一下java中的線程池是如何運(yùn)行我們提交的任務(wù)的,詳細(xì)流程比較復(fù)雜,這里我們不關(guān)注,我們只關(guān)注任務(wù)執(zhí)行的部分。java中的線程池用的是ThreadPoolExecutor,真正執(zhí)行代碼的部分是runWorker方法:final void runWorker(Worker w)

可以看到,程序會(huì)捕獲包括Error在內(nèi)的所有異常,并且在程序最后,將出現(xiàn)過(guò)的異常和當(dāng)前任務(wù)傳遞給afterExecute方法。

而ThreadPoolExecutor中的afterExecute方法是沒(méi)有任何實(shí)現(xiàn)的。

protected

存在問(wèn)題

想象下ThreadPoolExecutor這種處理方式會(huì)有什么問(wèn)題?

這樣做能夠保證我們提交的任務(wù)拋出了異常不會(huì)影響其他任務(wù)的執(zhí)行,同時(shí)也不會(huì)對(duì)用來(lái)執(zhí)行該任務(wù)的線程產(chǎn)生任何影響。

問(wèn)題就在afterExecute方法上, 這個(gè)方法沒(méi)有做任何處理,所以如果我們的任務(wù)拋出了異常,我們也無(wú)法立刻感知到。 即使感知到了,也無(wú)法查看異常信息。

所以,作為一名好的開(kāi)發(fā)者,是不應(yīng)該允許這種情況出現(xiàn)的。

如何避免這種問(wèn)題

思路很簡(jiǎn)單。

1、在提交的任務(wù)中將異常捕獲并處理,不拋給線程池。

2、異常拋給線程池,但是我們要及時(shí)處理拋出的異常。

直接catch

第一種思路很簡(jiǎn)單,就是我們提交任務(wù)的時(shí)候,將所有可能的異常都Catch住,并且自己處理。

說(shuō)白了就是把業(yè)務(wù)邏輯都trycatch起來(lái)。
但是這種思路的缺點(diǎn)就是:
1)所有的不同任務(wù)類(lèi)型都要trycatch,增加了代碼量。
2)不存在checkedexception的地方也需要都trycatch起來(lái),代碼丑陋。

線程池實(shí)現(xiàn)

第二種思路就可以避免上面的兩個(gè)問(wèn)題。

第二種思路又有以下四種實(shí)現(xiàn)方式

自定義線程池

自定義線程池,繼承ThreadPoolExecutor并復(fù)寫(xiě)其afterExecute(Runnable r, Throwable t)方法。

實(shí)現(xiàn)Thread.UncaughtExceptionHandler接口

實(shí)現(xiàn)Thread.UncaughtExceptionHandler接口,
實(shí)現(xiàn)void uncaughtException(Thread t, Throwable e);方法,
并將該handler傳遞給線程池的ThreadFactory

繼承ThreadGroup

覆蓋其uncaughtException方法。(與第二種方式類(lèi)似,因?yàn)門(mén)hreadGroup類(lèi)本身就實(shí)現(xiàn)了Thread.UncaughtExceptionHandler接口)

尤其注意:上面三種方式針對(duì)的都是通過(guò)execute(xx)的方式提交任務(wù),如果你提交任務(wù)用的是submit()方法,那么上面的三種方式都將不起作用,而應(yīng)該使用下面的方式

采用Future模式

如果提交任務(wù)的時(shí)候使用的方法是submit,那么該方法將返回一個(gè)Future對(duì)象,所有的異常以及處理結(jié)果都可以通過(guò)future對(duì)象獲取。
采用Future模式,將返回結(jié)果以及異常放到Future中,在Future中處理

總結(jié)

文章探討了從用戶層面的代碼到線程池層面的各種改造方法,力求讓業(yè)務(wù)代碼更加健壯可控。異常處理是java中非常重要的流程,但是線程池的默認(rèn)操作,會(huì)使的這些內(nèi)容被靜悄悄的忽略,這在某些情況下是致命的。

原作者:sanshao
原文鏈接:Java線程池執(zhí)行的任務(wù)拋出異常看不到日志詳解_編程語(yǔ)言_IT蝦米網(wǎng)
原出處:蝦米網(wǎng)

總結(jié)

以上是生活随笔為你收集整理的java异常_Java线程池「异常处理」正确姿势:有病就得治的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。