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

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

深入分析JAVA 多線程--interrupt()和線程終止方式

瀏覽:4日期:2022-08-30 15:14:10

一、interrupt() 介紹

interrupt() 定義在 Thread 類中,作用是中斷本線程。

本線程中斷自己是被允許的;其它線程調(diào)用本線程的 interrupt() 方法時(shí),會(huì)通過(guò) checkAccess() 檢查權(quán)限。這有可能拋出 SecurityException 異常。如果本線程是處于阻塞狀態(tài):調(diào)用線程的 wait() , wait(long) 或 wait(long, int) 會(huì)讓它進(jìn)入等待(阻塞)狀態(tài),或者調(diào)用線程的 join(),join(long),join(long, int),sleep(long),sleep(long, int) 也會(huì)讓它進(jìn)入阻塞狀態(tài)。若線程在阻塞狀態(tài)時(shí),調(diào)用了它的 interrupt() 方法,那么它的“中斷狀態(tài)”會(huì)被清除并且會(huì)收到一個(gè) InterruptedException 異常。例如,線程通過(guò) wait() 進(jìn)入阻塞狀態(tài),此時(shí)通過(guò) interrupt() 中斷該線程;調(diào)用 interrupt() 會(huì)立即將線程的中斷標(biāo)記設(shè)為 true,但是由于線程處于阻塞狀態(tài),所以該“中斷標(biāo)記”會(huì)立即被清除為 “false”,同時(shí),會(huì)產(chǎn)生一個(gè) InterruptedException 的異常。如果線程被阻塞在一個(gè) Selector 選擇器中,那么通過(guò) interrupt() 中斷它時(shí);線程的中斷標(biāo)記會(huì)被設(shè)置為 true,并且它會(huì)立即從選擇操作中返回。如果不屬于前面所說(shuō)的情況,那么通過(guò) interrupt() 中斷線程時(shí),它的中斷標(biāo)記會(huì)被設(shè)置為 true。中斷一個(gè)“已終止的線程”不會(huì)產(chǎn)生任何操作。

二、線程終止方式

Thread中的 stop() 和 suspend() 方法,由于固有的不安全性,已經(jīng)建議不再使用!下面,我先分別討論線程在“阻塞狀態(tài)”和“運(yùn)行狀態(tài)”的終止方式,然后再總結(jié)出一個(gè)通用的方式。

(一)、終止處于“阻塞狀態(tài)”的線程.

通常,我們通過(guò)“中斷”方式終止處于“阻塞狀態(tài)”的線程。當(dāng)線程由于被調(diào)用了 sleep(),,wait(),join() 等方法而進(jìn)入阻塞狀態(tài);若此時(shí)調(diào)用線程的 interrupt() 將線程的中斷標(biāo)記設(shè)為 true。由于處于阻塞狀態(tài),中斷標(biāo)記會(huì)被清除,同時(shí)產(chǎn)生一個(gè)InterruptedException 異常。將 InterruptedException 放在適當(dāng)?shù)奈恢镁湍芙K止線程,形式如下:

public void run() { try { while (true) { // 執(zhí)行業(yè)務(wù) } } catch (InterruptedException ie) { // 由于產(chǎn)生InterruptedException異常,退出while(true)循環(huán),線程終止! }}

說(shuō)明:

在while(true)中不斷的執(zhí)行業(yè)務(wù)代碼,當(dāng)線程處于阻塞狀態(tài)時(shí),調(diào)用線程的 interrupt() 產(chǎn)生 InterruptedException 中斷。中斷的捕獲在 while(true) 之外,這樣就退出了 while(true) 循環(huán)!

注意:

對(duì) InterruptedException 的捕獲務(wù)一般放在 while(true) 循環(huán)體的外面,這樣,在產(chǎn)生異常時(shí)就退出了 while(true) 循環(huán)。否則,InterruptedException 在 while(true) 循環(huán)體之內(nèi),就需要額外的添加退出處理。形式如下:

public void run() { while (true) { try { // 執(zhí)行任務(wù)... } catch (InterruptedException ie) { // InterruptedException在while(true)循環(huán)體內(nèi)。 // 當(dāng)線程產(chǎn)生了InterruptedException異常時(shí),while(true)仍能繼續(xù)運(yùn)行!需要手動(dòng)退出 break; } }}

說(shuō)明:

上面的 InterruptedException 異常的捕獲在 whle(true) 之內(nèi)。當(dāng)產(chǎn)生 InterruptedException 異常時(shí),被 catch 處理之外,仍然在 while(true) 循環(huán)體內(nèi);要退出 while(true) 循環(huán)體,需要額外的執(zhí)行退出while(true) 的操作。

(二)、終止處于“運(yùn)行狀態(tài)”的線程

通常,我們通過(guò)“標(biāo)記”方式終止處于“運(yùn)行狀態(tài)”的線程。其中,包括“中斷標(biāo)記”和“額外添加標(biāo)記”。

1、通過(guò)“中斷標(biāo)記”終止線程

public void run() { while (!isInterrupted()) { // 執(zhí)行任務(wù)... }}

說(shuō)明:

isInterrupted() 是判斷線程的中斷標(biāo)記是不是為 true。當(dāng)線程處于運(yùn)行狀態(tài),并且我們需要終止它時(shí);可以調(diào)用線程的 interrupt() 方法,使用線程的中斷標(biāo)記為 true,即 isInterrupted() 會(huì)返回true。此時(shí),就會(huì)退出while循環(huán)。

注意:interrupt() 并不會(huì)終止處于“運(yùn)行狀態(tài)”的線程!它會(huì)將線程的中斷標(biāo)記設(shè)為 true。

2、通過(guò)“額外添加標(biāo)記”終止線程

private volatile boolean flag= true;protected void stopTask() { flag = false;}public void run() { while (flag) { // 執(zhí)行任務(wù)... }}

說(shuō)明:

線程中有一個(gè) flag 標(biāo)記,它的默認(rèn)值是 true;并且我們提供 stopTask() 來(lái)設(shè)置 flag 標(biāo)記。當(dāng)我們需要終止該線程時(shí),調(diào)用該線程的 stopTask() 方法就可以讓線程退出 while 循環(huán)。

注意:將 flag 定義為 volatile 類型,是為了保證 flag 的可見(jiàn)性。即其它線程通過(guò) stopTask() 修改了 flag 之后,本線程能看到修改后的 flag 的值。

(三)、通過(guò)方式

綜合線程處于“阻塞狀態(tài)”和“運(yùn)行狀態(tài)”的終止方式,比較通用的終止線程的形式如下:

public void run() { try { // 1. isInterrupted()保證,只要中斷標(biāo)記為true就終止線程。 while (!isInterrupted()) { // 執(zhí)行任務(wù)... } } catch (InterruptedException ie) { // 2. InterruptedException異常保證,當(dāng)InterruptedException異常產(chǎn)生時(shí),線程被終止。 }}

1、isInterrupted()保證,只要中斷標(biāo)記為 true 就終止線程。2、InterruptedException 異常保證,當(dāng) InterruptedException 異常產(chǎn)生時(shí),線程被終止。

三、示例

public class InterruptTest { public static void main(String[] args) { try { Thread t1 = new MyThread('t1'); // 新建線程t1 System.out.println(t1.getName() + '[' + t1.getState() + '] is new.'); t1.start();// 啟動(dòng)線程t1 System.out.println(t1.getName() + '[' + t1.getState() + '] is started.'); Thread.sleep(300);// 休眠300毫秒,然后主線程給t1發(fā)“中斷”指令,查看t1狀態(tài) t1.interrupt(); System.out.println(t1.getName() + '[' + t1.getState() + '] is interrupted.'); Thread.sleep(300);// 休眠300毫秒,然后查看t1狀態(tài) System.out.println(t1.getName() + '[' + t1.getState() + '] is interrupted now.'); }catch(InterruptedException e) { e.printStackTrace(); } }}class MyThread extends Thread{ public MyThread(String name) { super(name); } @Override public void run() { try { int i = 0; while(!isInterrupted()) {Thread.sleep(100);// 休眠100毫秒++i;System.out.println(Thread.currentThread().getName() + '[' + this.getState() + '] loop ' + i); } }catch(InterruptedException e) { System.out.println(Thread.currentThread().getName() + '[' + this.getState() + '] catch InterruptedException'); } }}

運(yùn)行結(jié)果

t1 [ NEW ] is new.t1 [ RUNNABLE ] is started.t1 [ RUNNABLE ] loop 1t1 [ RUNNABLE ] loop 2t1 [ RUNNABLE ] loop 3t1 [ RUNNABLE ] catch InterruptedExceptiont1 [ TERMINATED ] is interrupted.t1 [ TERMINATED ] is interrupted now.

說(shuō)明:

①、主線程 main 中通過(guò) new MyThread('t1') 創(chuàng)建線程 t1,之后通過(guò) t1.start() 啟動(dòng)線程 t1。

②、t1 啟動(dòng)之后,會(huì)不斷的檢查它的中斷標(biāo)記,如果中斷標(biāo)記為“false”;則休眠 100ms。

③、t1 休眠之后,會(huì)切換到主線程main;主線程再次運(yùn)行時(shí),會(huì)執(zhí)行t1.interrupt()中斷線程t1。t1收到中斷指令之后,會(huì)將t1的中斷標(biāo)記設(shè)置“false”,而且會(huì)拋出 InterruptedException 異常。在 t1 的 run() 方法中,是在循環(huán)體 while 之外捕獲的異常;因此循環(huán)被終止。

我們對(duì)上面的結(jié)果進(jìn)行小小的修改,將run()方法中捕獲InterruptedException異常的代碼塊移到while循環(huán)體內(nèi)。

public class InterruptTest { public static void main(String[] args) { try { Thread t1 = new MyThread('t1'); // 新建線程t1 System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is new.'); t1.start();// 啟動(dòng)線程t1 System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is started.'); Thread.sleep(300);// 休眠300毫秒,然后主線程給t1發(fā)“中斷”指令,查看t1狀態(tài) t1.interrupt(); System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is interrupted.'); Thread.sleep(300);// 休眠300毫秒,然后查看t1狀態(tài) System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is interrupted now.'); }catch(InterruptedException e) { e.printStackTrace(); } }}class MyThread extends Thread{ public MyThread(String name) { super(name); } @Override public void run() { int i = 0; while(!isInterrupted()) { try {Thread.sleep(100); // 休眠100ms } catch (InterruptedException ie) { System.out.println(Thread.currentThread().getName() +' [ '+this.getState()+' ] catch InterruptedException.'); } i++; System.out.println(Thread.currentThread().getName()+' [ '+this.getState()+' ] loop ' + i); } }}

運(yùn)行結(jié)果

t1 [ NEW ] is new.t1 [ RUNNABLE ] is started.t1 [ RUNNABLE ] loop 1t1 [ RUNNABLE ] loop 2t1 [ TIMED_WAITING ] is interrupted.t1 [ RUNNABLE ] catch InterruptedException.t1 [ RUNNABLE ] loop 3t1 [ RUNNABLE ] loop 4t1 [ RUNNABLE ] loop 5t1 [ RUNNABLE ] loop 6t1 [ RUNNABLE ] is interrupted now.t1 [ RUNNABLE ] loop 7...... // 無(wú)限循環(huán)

說(shuō)明:

程序進(jìn)入了死循環(huán)了。

這是因?yàn)椋瑃1在“等待(阻塞)狀態(tài)”時(shí),被 interrupt() 中斷;此時(shí),會(huì)清除中斷標(biāo)記(即 isInterrupted() 會(huì)返回 false),而且會(huì)拋出 InterruptedException 異常(該異常在while循環(huán)體內(nèi)被捕獲)。因此,t1理所當(dāng)然的會(huì)進(jìn)入死循環(huán)了。

解決該問(wèn)題,需要我們?cè)诓东@異常時(shí),額外的進(jìn)行退出 while 循環(huán)的處理。例如,在 MyThread 的 catch(InterruptedException) 中添加 break 或 return 就能解決該問(wèn)題。

下面是通過(guò)“額外添加標(biāo)記”的方式終止“狀態(tài)狀態(tài)”的線程的示例:

public class InterruptTest { public static void main(String[] args) { try { MyThread t1 = new MyThread('t1'); // 新建線程t1 System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is new.'); t1.start();// 啟動(dòng)線程t1 System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is started.'); Thread.sleep(300);// 休眠300毫秒,然后主線程給t1發(fā)“中斷”指令,查看t1狀態(tài) t1.stopTask(); System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is interrupted.'); Thread.sleep(300);// 休眠300毫秒,然后查看t1狀態(tài) System.out.println(t1.getName() + ' [ ' + t1.getState() + ' ] is interrupted now.'); }catch(InterruptedException e) { e.printStackTrace(); } }}class MyThread extends Thread{ private volatile boolean flag = true; public void stopTask() { flag = false; } public MyThread(String name) { super(name); } @Override public void run() { synchronized (this) { int i = 0; while(flag) {try { Thread.sleep(100); // 休眠100ms} catch (InterruptedException ie) { System.out.println(Thread.currentThread().getName() +' [ '+this.getState()+' ] catch InterruptedException.'); break;}i++;System.out.println(Thread.currentThread().getName()+' [ '+this.getState()+' ] loop ' + i); } } }}

運(yùn)行結(jié)果

t1 [ NEW ] is new.t1 [ RUNNABLE ] is started.t1 [ RUNNABLE ] loop 1t1 [ RUNNABLE ] loop 2t1 [ RUNNABLE ] loop 3t1 [ RUNNABLE ] is interrupted.t1 [ TERMINATED ] is interrupted now.

四、interrupted() 和 isInterrupted()的區(qū)別

interrupted() 和 isInterrupted()都能夠用于檢測(cè)對(duì)象的“中斷標(biāo)記”。區(qū)別是,interrupted() 除了返回中斷標(biāo)記之外,它還會(huì)清除中斷標(biāo)記(即將中斷標(biāo)記設(shè)為 false);而 isInterrupted() 僅僅返回中斷標(biāo)記。

以上就是深入分析JAVA 多線程--interrupt()和線程終止方式的詳細(xì)內(nèi)容,更多關(guān)于JAVA 多線程--interrupt()和線程終止的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 专注氟塑料泵_衬氟泵_磁力泵_卧龙泵阀_化工泵专业品牌 - 梭川泵阀 | 电气控制系统集成商-PLC控制柜变频控制柜-非标自动化定制-电气控制柜成套-NIDEC CT变频器-威肯自动化控制 | 沉降天平_沉降粒度仪_液体比重仪-上海方瑞仪器有限公司 | 德国GMN轴承,GMN角接触球轴承,GMN单向轴承,GMN油封,GMN非接触式密封 | 金环宇|金环宇电线|金环宇电缆|金环宇电线电缆|深圳市金环宇电线电缆有限公司|金环宇电缆集团 | 在线浊度仪_悬浮物污泥浓度计_超声波泥位计_污泥界面仪_泥水界面仪-无锡蓝拓仪表科技有限公司 | 快干水泥|桥梁伸缩缝止水胶|伸缩缝装置生产厂家-广东广航交通科技有限公司 | 捷码低代码平台 - 3D数字孪生_大数据可视化开发平台「免费体验」 | 欧洲MV日韩MV国产_人妻无码一区二区三区免费_少妇被 到高潮喷出白浆av_精品少妇自慰到喷水AV网站 | 钢托盘,钢制托盘,立库钢托盘,金属托盘制造商_南京飞天金属制品实业有限公司 | 并离网逆变器_高频UPS电源定制_户用储能光伏逆变器厂家-深圳市索克新能源 | 无锡网站建设-做网站-建网站-网页设计制作-阿凡达建站公司 | 一体化污水处理设备,一体化污水设备厂家-宜兴市福源水处理设备有限公司 | 天津仓库出租网-天津电商仓库-天津云仓一件代发-【博程云仓】 | 德州万泰装饰 - 万泰装饰装修设计软装家居馆 | 光环国际-新三板公司_股票代码:838504 | 丹佛斯变频器-丹佛斯压力开关-变送器-广州市风华机电设备有限公司 | 石家庄救护车出租_重症转院_跨省跨境医疗转送_活动赛事医疗保障_康复出院_放弃治疗_腾康26年医疗护送转诊团队 | 干粉砂浆设备-干粉砂浆生产线-干混-石膏-保温砂浆设备生产线-腻子粉设备厂家-国恒机械 | 半自动预灌装机,卡式瓶灌装机,注射器灌装机,给药器灌装机,大输液灌装机,西林瓶灌装机-长沙一星制药机械有限公司 | 企典软件一站式企业管理平台,可私有、本地化部署!在线CRM客户关系管理系统|移动办公OA管理系统|HR人事管理系统|人力 | 胶水,胶粘剂,AB胶,环氧胶,UV胶水,高温胶,快干胶,密封胶,结构胶,电子胶,厌氧胶,高温胶水,电子胶水-东莞聚力-聚厉胶粘 | 重庆小面培训_重庆小面技术培训学习班哪家好【终身免费复学】 | 合肥宠物店装修_合肥宠物美容院装修_合肥宠物医院设计装修公司-安徽盛世和居装饰 | 清洁设备_洗地机/扫地机厂家_全自动洗地机_橙犀清洁设备官网 | 上海网站建设-上海网站制作-上海网站设计-上海做网站公司-咏熠软件 | 能耗监测系统-节能监测系统-能源管理系统-三水智能化 | 全自动包装秤_全自动上袋机_全自动套袋机_高位码垛机_全自动包装码垛系统生产线-三维汉界机器(山东)股份有限公司 | 天一线缆邯郸有限公司_煤矿用电缆厂家_矿用光缆厂家_矿用控制电缆_矿用通信电缆-天一线缆邯郸有限公司 | 土壤水分自动监测站-SM150便携式土壤水分仪-铭奥仪器 | KBX-220倾斜开关|KBW-220P/L跑偏开关|拉绳开关|DHJY-I隔爆打滑开关|溜槽堵塞开关|欠速开关|声光报警器-山东卓信有限公司 | SRRC认证|CCC认证|CTA申请_IMEI|MAC地址注册-英利检测 | 高压无油空压机_无油水润滑空压机_水润滑无油螺杆空压机_无油空压机厂家-科普柯超滤(广东)节能科技有限公司 | 温室大棚建设|水肥一体化|物联网系统 | 超声波电磁流量计-液位计-孔板流量计-料位计-江苏信仪自动化仪表有限公司 | 烟台条码打印机_烟台条码扫描器_烟台碳带_烟台数据采集终端_烟台斑马打印机-金鹏电子-金鹏电子 | TPM咨询,精益生产管理,5S,6S现场管理培训_华谋咨询公司 | 地源热泵一体机,地源热泵厂家-淄博汇能环保设备有限公司 | 圆形振动筛_圆筛_旋振筛_三次元振动筛-河南新乡德诚生产厂家 | 流量卡中心-流量卡套餐查询系统_移动电信联通流量卡套餐大全 | 德国GMN轴承,GMN角接触球轴承,GMN单向轴承,GMN油封,GMN非接触式密封 |