电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

Java ThreadPool的使用解析

瀏覽:5日期:2022-08-22 11:56:42

簡介

在java中,除了單個使用Thread之外,我們還會使用到ThreadPool來構(gòu)建線程池,那么在使用線程池的過程中需要注意哪些事情呢?

一起來看看吧。

java自帶的線程池

java提供了一個非常好用的工具類Executors,通過Executors我們可以非常方便的創(chuàng)建出一系列的線程池:

Executors.newCachedThreadPool,根據(jù)需要可以創(chuàng)建新線程的線程池。線程池中曾經(jīng)創(chuàng)建的線程,在完成某個任務(wù)后也許會被用來完成另外一項任務(wù)。

Executors.newFixedThreadPool(int nThreads) ,創(chuàng)建一個可重用固定線程數(shù)的線程池。這個線程池里最多包含nThread個線程。

Executors.newSingleThreadExecutor() ,創(chuàng)建一個使用單個 worker 線程的 Executor。即使任務(wù)再多,也只用1個線程完成任務(wù)。

Executors.newSingleThreadScheduledExecutor() ,創(chuàng)建一個單線程執(zhí)行程序,它可安排在給定延遲后運行命令或者定期執(zhí)行。

提交給線程池的線程要是可以被中斷的

ExecutorService線程池提供了兩個很方便的停止線程池中線程的方法,他們是shutdown和shutdownNow。

shutdown不會接受新的任務(wù),但是會等待現(xiàn)有任務(wù)執(zhí)行完畢。而shutdownNow會嘗試立馬終止現(xiàn)有運行的線程。

那么它是怎么實現(xiàn)的呢?我們看一個ThreadPoolExecutor中的一個實現(xiàn):

public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(STOP); interruptWorkers(); tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }

里面有一個interruptWorkers()方法的調(diào)用,實際上就是去中斷當前運行的線程。

所以我們可以得到一個結(jié)論,提交到ExecutorService中的任務(wù)一定要是可以被中斷的,否則shutdownNow方法將會失效。

先看一個錯誤的使用例子:

public void wrongSubmit(){ Runnable runnable= ()->{ try(SocketChannel sc = SocketChannel.open(new InetSocketAddress('127.0.0.1', 8080))) { ByteBuffer buf = ByteBuffer.allocate(1024); while(true){sc.read(buf); } } catch (IOException e) {e.printStackTrace(); } }; ExecutorService pool = Executors.newFixedThreadPool(10); pool.submit(runnable); pool.shutdownNow(); }

在這個例子中,運行的代碼無法處理中斷,所以將會一直運行。

下面看下正確的寫法:

public void correctSubmit(){ Runnable runnable= ()->{ try(SocketChannel sc = SocketChannel.open(new InetSocketAddress('127.0.0.1', 8080))) {ByteBuffer buf = ByteBuffer.allocate(1024);while(!Thread.interrupted()){ sc.read(buf);} } catch (IOException e) {e.printStackTrace(); } }; ExecutorService pool = Executors.newFixedThreadPool(10); pool.submit(runnable); pool.shutdownNow(); }

我們需要在while循環(huán)中加上中斷的判斷,從而控制程序的執(zhí)行。

正確處理線程池中線程的異常

如果在線程池中的線程發(fā)生了異常,比如RuntimeException,我們怎么才能夠捕捉到呢? 如果不能夠?qū)Ξ惓_M行合理的處理,那么將會產(chǎn)生不可預(yù)料的問題。

看下面的例子:

public void wrongSubmit() throws InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(10); Runnable runnable= ()->{ throw new NullPointerException(); }; pool.execute(runnable); Thread.sleep(5000); System.out.println('finished!'); }

上面的例子中,我們submit了一個任務(wù),在任務(wù)中會拋出一個NullPointerException,因為是非checked異常,所以不需要顯式捕獲,在任務(wù)運行完畢之后,我們基本上是不能夠得知任務(wù)是否運行成功了。

那么,怎么才能夠捕獲這樣的線程池異常呢?這里介紹大家?guī)讉€方法。

第一種方法就是繼承ThreadPoolExecutor,重寫

protected void afterExecute(Runnable r, Throwable t) { }

protected void terminated() { }

這兩個方法。

其中afterExecute會在任務(wù)執(zhí)行完畢之后被調(diào)用,Throwable t中保存的是可能出現(xiàn)的運行時異常和Error。我們可以根據(jù)需要進行處理。

而terminated是在線程池中所有的任務(wù)都被調(diào)用完畢之后才被調(diào)用的。我們可以在其中做一些資源的清理工作。

第二種方法就是使用UncaughtExceptionHandler。

Thread類中提供了一個setUncaughtExceptionHandler方法,用來處理捕獲的異常,我們可以在創(chuàng)建Thread的時候,為其添加一個UncaughtExceptionHandler就可以了。

但是ExecutorService執(zhí)行的是一個個的Runnable,怎么使用ExecutorService來提交Thread呢?

別怕, Executors在構(gòu)建線程池的時候,還可以讓我們傳入ThreadFactory,從而構(gòu)建自定義的Thread。

public void useExceptionHandler() throws InterruptedException { ThreadFactory factory =new ExceptionThreadFactory(new MyExceptionHandler()); ExecutorService pool =Executors.newFixedThreadPool(10, factory); Runnable runnable= ()->{ throw new NullPointerException(); }; pool.execute(runnable); Thread.sleep(5000); System.out.println('finished!'); } public static class ExceptionThreadFactory implements ThreadFactory { private static final ThreadFactory defaultFactory =Executors.defaultThreadFactory(); private final Thread.UncaughtExceptionHandler handler; public ExceptionThreadFactory(Thread.UncaughtExceptionHandler handler) { this.handler = handler; } @Override public Thread newThread(Runnable run) { Thread thread = defaultFactory.newThread(run); thread.setUncaughtExceptionHandler(handler); return thread; } } public static class MyExceptionHandler implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { } }

上面的例子有點復(fù)雜了, 有沒有更簡單點的做法呢?

有的。ExecutorService除了execute來提交任務(wù)之外,還可以使用submit來提交任務(wù)。不同之處是submit會返回一個Future來保存執(zhí)行的結(jié)果。

public void useFuture() throws InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(10); Runnable runnable= ()->{ throw new NullPointerException(); }; Future future = pool.submit(runnable); try { future.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } Thread.sleep(5000); System.out.println('finished!'); }

當我們在調(diào)用future.get()來獲取結(jié)果的時候,異常也會被封裝到ExecutionException,我們可以直接獲取到。

線程池中使用ThreadLocal一定要注意清理

我們知道ThreadLocal是Thread中的本地變量,如果我們在線程的運行過程中用到了ThreadLocal,那么當線程被回收之后再次執(zhí)行其他的任務(wù)的時候就會讀取到之前被設(shè)置的變量,從而產(chǎn)生未知的問題。

正確的使用方法就是在線程每次執(zhí)行完任務(wù)之后,都去調(diào)用一下ThreadLocal的remove操作。

或者在自定義ThreadPoolExecutor中,重寫beforeExecute(Thread t, Runnable r)方法,在其中加入ThreadLocal的remove操作。

本文的代碼:

https://github.com/ddean2009/learn-java-base-9-to-20/tree/master/security

以上就是Java ThreadPool的使用解析的詳細內(nèi)容,更多關(guān)于Java ThreadPool的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標簽: Java
相關(guān)文章:
主站蜘蛛池模板: 不锈钢复合板|钛复合板|金属复合板|南钢集团安徽金元素复合材料有限公司-官网 | 碳纤维布-植筋胶-灌缝胶-固特嘉加固材料公司 | 车间除尘设备,VOCs废气处理,工业涂装流水线,伸缩式喷漆房,自动喷砂房,沸石转轮浓缩吸附,机器人喷粉线-山东创杰智慧 | 跨境物流_美国卡派_中大件运输_尾程派送_海外仓一件代发 - 广州环至美供应链平台 | 定量包装机,颗粒定量包装机,粉剂定量包装机,背封颗粒包装机,定量灌装机-上海铸衡电子科技有限公司 | 大学食堂装修设计_公司餐厅效果图_工厂食堂改造_迈普装饰 | 酒水灌装机-白酒灌装机-酒精果酒酱油醋灌装设备_青州惠联灌装机械 | 工业胀紧套_万向节联轴器_链条-规格齐全-型号选购-非标订做-厂家批发价格-上海乙谛精密机械有限公司 | B2B网站_B2B免费发布信息网站_B2B企业贸易平台 - 企资网 | 大型工业风扇_工业大风扇_大吊扇_厂房车间降温-合昌大风扇 | 上海公众号开发-公众号代运营公司-做公众号的公司企业服务商-咏熠软件 | 锻造液压机,粉末冶金,拉伸,坩埚成型液压机定制生产厂家-山东威力重工官方网站 | 杭州画室_十大画室_白墙画室_杭州美术培训_国美附中培训_附中考前培训_升学率高的画室_美术中考集训美术高考集训基地 | 地埋式垃圾站厂家【佳星环保】小区压缩垃圾中转站转运站 | Trimos测长机_测高仪_TESA_mahr,WYLER水平仪,PWB对刀仪-德瑞华测量技术(苏州)有限公司 | 低温柔性试验仪-土工布淤堵-沥青车辙试验仪-莱博特(天津)试验机有限公司 | 盘装氧量分析仪-防爆壁挂氧化锆分析仪-安徽吉帆仪表有限公司 | 硅胶布|电磁炉垫片|特氟龙胶带-江苏浩天复合材料有限公司 | atcc网站,sigma试剂价格,肿瘤细胞现货,人结肠癌细胞株购买-南京科佰生物 | 洛阳防爆合格证办理-洛阳防爆认证机构-洛阳申请国家防爆合格证-洛阳本安防爆认证代办-洛阳沪南抚防爆电气技术服务有限公司 | 苏州防水公司_厂房屋面外墙防水_地下室卫生间防水堵漏-苏州伊诺尔防水工程有限公司 | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | 一体化污水处理设备-一体化净水设备-「山东梦之洁水处理」 | 洛阳网站建设_洛阳网站优化_网站建设平台_洛阳香河网络科技有限公司 | 伸缩节_伸缩器_传力接头_伸缩接头_巩义市联通管道厂 | 视觉检测设备_自动化检测设备_CCD视觉检测机_外观缺陷检测-瑞智光电 | 防爆电机生产厂家,YBK3电动机,YBX3系列防爆电机,YBX4节防爆电机--河南省南洋防爆电机有限公司 | 减速机三参数组合探头|TSM803|壁挂式氧化锆分析仪探头-安徽鹏宸电气有限公司 | 科箭WMS仓库管理软件-TMS物流管理系统-科箭SaaS云服务 | 天长市晶耀仪表有限公司| 合肥网带炉_安徽箱式炉_钟罩炉-合肥品炙装备科技有限公司 | 兰州UPS电源,兰州山特UPS-兰州万胜商贸 | 中视电广_短视频拍摄_短视频推广_短视频代运营_宣传片拍摄_影视广告制作_中视电广 | 昊宇水工|河北昊宇水工机械工程有限公司 | 广州冷却塔维修厂家_冷却塔修理_凉水塔风机电机填料抢修-广东康明节能空调有限公司 | 橡胶膜片,夹布膜片,橡胶隔膜密封,泵阀设备密封膜片-衡水汉丰橡塑科技公司网站 | 旋振筛|圆形摇摆筛|直线振动筛|滚筒筛|压榨机|河南天众机械设备有限公司 | 机械加工_绞车配件_立式离心机_减速机-洛阳三永机械厂 | 电脑刺绣_绣花厂家_绣花章仔_织唛厂家-[源欣刺绣]潮牌刺绣打版定制绣花加工厂家 | 澳洁干洗店加盟-洗衣店干洗连锁「澳洁干洗免费一对一贴心服务」 干洗加盟网-洗衣店品牌排行-干洗设备价格-干洗连锁加盟指南 | 砖机托板价格|免烧砖托板|空心砖托板厂家_山东宏升砖机托板厂 |