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

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

詳解Java 線(xiàn)程中斷

瀏覽:98日期:2022-08-16 15:57:54
一、前言

大家肯定都使用過(guò) Java 線(xiàn)程開(kāi)發(fā)(Thread / Runnable),啟動(dòng)一個(gè)線(xiàn)程的做法通常是:

new Thread(new Runnable( @Override public void run() { // todo sth... })).start();

然而線(xiàn)程退出,大家是如何做的呢?一般做法可能不外乎以下兩種:

設(shè)置一個(gè)標(biāo)志位:true / false 來(lái)退出; 強(qiáng)制退出:thread.stop;(我相信,現(xiàn)在應(yīng)該沒(méi)人會(huì)使用這種方式了,因?yàn)镴DK也很早就廢棄了該方法)

可能還會(huì)有人提出,我可以用中斷來(lái)退出線(xiàn)程! 我只能說(shuō):Too Young Too Simple!中斷并不會(huì)使得線(xiàn)程結(jié)束而退出,中斷(interrupt)只是喚醒被阻塞的線(xiàn)程而已。

本篇,我們就來(lái)好好的聊聊:線(xiàn)程中斷,以及如何正確的使用線(xiàn)程中斷,和正確的線(xiàn)程退出。

二、為何 Thread.stop 被廢棄

This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.

以上是官方 JDK 中的源碼注釋說(shuō)明,其含義如下:

**Thread.stop 方法天生就不安全。**使用該方法來(lái)停止線(xiàn)程,將會(huì)導(dǎo)致其它因?yàn)楸O(jiān)視器鎖『監(jiān)視器我們?cè)?synchronized 中就講過(guò),是 Java 的內(nèi)置鎖』而被鎖住的線(xiàn)程全部都解鎖!(本質(zhì)的后果是:沒(méi)有檢查的 ThreadDeath 異常會(huì)在棧中傳播,因而使得監(jiān)視器鎖解鎖)。如果任何一個(gè)被監(jiān)視器鎖給鎖住的對(duì)象處于一個(gè)不一致的狀態(tài),那么其被解鎖后將會(huì)被其它線(xiàn)程可見(jiàn),潛在的結(jié)果是產(chǎn)生任何后果。**我們應(yīng)該使用一個(gè)變量來(lái)代替使用 stop 方法,告訴目標(biāo)線(xiàn)程退出『這里就是我們開(kāi)頭所說(shuō)的第一種方法,設(shè)置一個(gè)標(biāo)志位』。**目標(biāo)線(xiàn)程應(yīng)該周期性的檢查這個(gè)變量,并根據(jù)這個(gè)變量來(lái)正確的退出 run 方法。如果目標(biāo)線(xiàn)程處于阻塞/休眠狀態(tài)(如:使用 wait、sleep、yield 方法后,線(xiàn)程讓出了 CPU 使用權(quán),進(jìn)而阻塞/休眠),此時(shí),該標(biāo)志位變量將不會(huì)起作用,那么,應(yīng)該使用 interrupt 方法來(lái)中斷目標(biāo)線(xiàn)程的阻塞/休眠狀態(tài),將其喚醒!

對(duì)于 ThreadDeath 對(duì)象,官方還有補(bǔ)充:

線(xiàn)程可以在幾乎任何地方拋出 ThreadDeath 異常。由于這一點(diǎn),所有的同步方法和(代碼)塊將必須被考慮得事無(wú)巨細(xì)。 線(xiàn)程在清理第一個(gè) ThreadDeath 異常的時(shí)候(在 catch 或 finally 語(yǔ)句中),可能會(huì)拋出第二個(gè)。清理工作將不得不重復(fù)直到到其成功。保障這一點(diǎn)的代碼將會(huì)很復(fù)雜。

所以,我們也別想著去 try-catch ThreadDeath Exception!

同樣,被廢棄的還有 Thread.resume 和 Thread.suspend。這倆方法有造成死鎖的危險(xiǎn):

使用suspend時(shí),并不會(huì)釋放鎖; 如果存在某種情況要先獲取該鎖,再進(jìn)行resume,那么就造成死鎖了;

取代這兩方法的正確方式是:Object.wait 和 Object.notify :

因?yàn)?Object.wait 進(jìn)入阻塞時(shí),會(huì)釋放鎖。

三、線(xiàn)程中斷的含義

Thread 中有三個(gè)與中斷相關(guān)的方法:

成員方法 interrupt():設(shè)置線(xiàn)程中斷標(biāo)志為 true ; 成員方法 isInterrupted():獲取線(xiàn)程的中斷狀態(tài),默認(rèn)為 false,調(diào)用 interrupt() 后,該方法返回 true; 靜態(tài)方法 Thread.interrupted():獲取線(xiàn)程的中斷狀態(tài),并且清除中斷狀態(tài)(設(shè)置為 false);

注:如果線(xiàn)程中斷后,連續(xù)兩次調(diào)用 Thread.interrupted(),第一次是 true & 清除狀態(tài),第二次結(jié)果是 false。

3.1、初步了解

我們先來(lái)通過(guò)一個(gè)例子來(lái)初步了解 thread.interrupt :

public class InterruptDemo implements Runnable { @Override public void run() { while (true) { System.out.println('Thread running...'); } } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new InterruptDemo(), 'InterruptDemo'); System.out.println('start thread'); thread.start(); Thread.sleep(50); System.out.println('interrupt thread'); thread.interrupt(); Thread.sleep(50); System.out.println('thread’s status = ' + thread.isInterrupted()); }}

輸出結(jié)果:

start threadThread running...Thread running.........interrupt threadThread running...Thread running.........thread’s status = trueThread running.........

我們可以看到,即便我們調(diào)用了 thread.interrupt 方法,線(xiàn)程也并沒(méi)有退出,仍舊繼續(xù)運(yùn)行。因此,這個(gè)例子證明了一點(diǎn):我們并不能通過(guò)'我們所認(rèn)為的'中斷來(lái)試圖'結(jié)束'正在運(yùn)行的線(xiàn)程。

3.2、中斷即喚醒阻塞/休眠的線(xiàn)程

同樣,我們?cè)賮?lái)看一個(gè)例子:

public class InterruptDemo implements Runnable { @Override public void run() { while (true) { System.out.println('Thread will sleep 10s ------------------------- running'); long timestamp = System.currentTimeMillis(); try { Thread.sleep(10000); } catch (InterruptedException e) { System.out.println('thread interrupted...'); } timestamp = System.currentTimeMillis() - timestamp; System.out.println('Thread run, total sleep = ' + timestamp + '(ms)'); } } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new InterruptDemo(), 'InterruptDemo'); System.out.println('start thread'); thread.start(); Thread.sleep(3000); System.out.println('interrupt thread'); thread.interrupt(); System.out.println('main exit'); }}

輸出結(jié)果:

start threadThread will sleep 10s ------------------------- runninginterrupt threadmain exitthread interrupted...Thread run, total sleep = 3002(ms)Thread will sleep 10s ------------------------- runningThread run, total sleep = 10002(ms)Thread will sleep 10s ------------------------- running

我們可以看到,線(xiàn)程啟動(dòng)后,進(jìn)入睡眠(10s),3秒后被中斷喚醒,執(zhí)行完一個(gè) while 后再次進(jìn)入第二次睡眠(10s),然后周而復(fù)始。

3.3、一般標(biāo)志位法退出線(xiàn)程

public class InterruptDemo implements Runnable { private static final AtomicBoolean running = new AtomicBoolean(true); @Override public void run() { while (running.get()) { long timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis() - timestamp; System.out.println('Thread run, total sleep = ' + timestamp + '(ms)'); } System.out.println('Thread exit'); } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new InterruptDemo(), 'InterruptDemo'); System.out.println('start thread'); thread.start(); Thread.sleep(100); System.out.println('interrupt thread'); thread.interrupt(); running.set(false); System.out.println('main exit'); }}

輸出結(jié)果:

start thread.......Thread run, total sleep = 0(ms)interrupt threadThread run, total sleep = 0(ms)Thread run, total sleep = 0(ms)Thread run, total sleep = 0(ms)main exitThread exit

我們通過(guò)使用一個(gè) AtomicBoolean 變量來(lái)當(dāng)作標(biāo)志位,使得我們的線(xiàn)程能正常退出。 我們也可以判斷線(xiàn)程是否被中斷而選擇性的退出。

3.4、線(xiàn)程中斷退出

public class InterruptDemo implements Runnable { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { long timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis() - timestamp; System.out.println('Thread run, total sleep = ' + timestamp + '(ms)'); } System.out.println('Thread exit'); } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new InterruptDemo(), 'InterruptDemo'); System.out.println('start thread'); thread.start(); Thread.sleep(100); System.out.println('interrupt thread'); thread.interrupt(); System.out.println('main exit'); }}

輸出結(jié)果:

start thread.......Thread run, total sleep = 0(ms)interrupt threadThread run, total sleep = 0(ms)Thread run, total sleep = 0(ms)Thread run, total sleep = 0(ms)main exitThread exit3.5、標(biāo)志位 + 線(xiàn)程中斷結(jié)合

public class InterruptDemo implements Runnable { private static final AtomicBoolean running = new AtomicBoolean(true); @Override public void run() { while (running.get()) { System.out.println('Thread will sleep 10s ------------------------- running'); long timestamp = System.currentTimeMillis(); try { Thread.sleep(10000); } catch (InterruptedException e) { System.out.println('Interrupted... Todo other things then exit......'); running.set(false); continue; } timestamp = System.currentTimeMillis() - timestamp; System.out.println('Thread run, total sleep = ' + timestamp + '(ms)'); } System.out.println('Thread exit'); } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new InterruptDemo(), 'InterruptDemo'); System.out.println('start thread'); thread.start(); Thread.sleep(3000); System.out.println('interrupt thread'); thread.interrupt(); System.out.println('main exit'); }}

輸出結(jié)果:

start threadThread will sleep 10s ------------------------- runninginterrupt threadmain exitInterrupted... Todo other things then exit......Thread exit四、總結(jié)

本文我們分析了線(xiàn)程的中斷,并讓大家了解了中斷的含義:只是告訴該線(xiàn)程,你被『中斷』了,至于你想干嘛,還是由你自己來(lái)決定。同時(shí),我們也簡(jiǎn)單分析了幾個(gè)廢棄的方法的原因。希望大家學(xué)習(xí)了本文之后,能正確且合理的設(shè)計(jì),線(xiàn)程如何安全的退出。

五、附錄 Object.wait:阻塞當(dāng)前線(xiàn)程,釋放持有的鎖; Object.notify:?jiǎn)拘旬?dāng)前對(duì)象上被阻塞的線(xiàn)程,使其進(jìn)入就緒狀態(tài); Object.notifyAll:?jiǎn)拘阉芯€(xiàn)程; Thread.sleep:指定當(dāng)前線(xiàn)程休眠一定時(shí)間,讓出CPU,但不會(huì)釋放同步資源鎖; Thread.yield:讓出CPU使用權(quán),讓自己和其它線(xiàn)程來(lái)爭(zhēng)奪使用CPU的機(jī)會(huì),因此,使用此方法后,并不能保證該線(xiàn)程又再次拿到CPU而恢復(fù)運(yùn)行(使用此方法后,優(yōu)先級(jí)高的線(xiàn)程拿到CPU的概率較大,但優(yōu)先級(jí)低的線(xiàn)程也有概率拿到CPU而執(zhí)行),同理不會(huì)釋放同步資源鎖;

以上就是詳解Java 線(xiàn)程中斷的詳細(xì)內(nèi)容,更多關(guān)于Java 線(xiàn)程中斷的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 青岛美佳乐清洁工程有限公司|青岛油烟管道清洗|酒店|企事业单位|学校工厂厨房|青岛油烟管道清洗 插针变压器-家用电器变压器-工业空调变压器-CD型电抗器-余姚市中驰电器有限公司 | 潍坊大集网-潍坊信息港-潍坊信息网 | 石膏基自流平砂浆厂家-高强石膏基保温隔声自流平-轻质抹灰石膏粉砂浆批发-永康市汇利建设有限公司 | 云南成人高考网| 搪玻璃冷凝器_厂家-越宏化工设备 | 卓能JOINTLEAN端子连接器厂家-专业提供PCB接线端子|轨道式端子|重载连接器|欧式连接器等电气连接产品和服务 | 电子厂招聘_工厂招聘_普工招聘_小时工招聘信息平台-众立方招工网 | 仿古瓦,仿古金属瓦,铝瓦,铜瓦,铝合金瓦-西安东申景观艺术工程有限公司 | 水热合成反应釜-防爆高压消解罐-西安常仪仪器设备有限公司 | 长沙中央空调维修,中央空调清洗维保,空气能热水工程,价格,公司就找维小保-湖南维小保环保科技有限公司 | 折弯机-刨槽机-数控折弯机-数控刨槽机-数控折弯机厂家-深圳豐科机械有限公司 | 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 金属清洗剂,防锈油,切削液,磨削液-青岛朗力防锈材料有限公司 | 氢氧化钙设备_厂家-淄博工贸有限公司 | 高低温老化试验机-步入式/低温恒温恒湿试验机-百科 | 冷凝水循环试验箱-冷凝水试验箱-可编程高低温试验箱厂家-上海巨为(www.juweigroup.com) | 真空乳化机-灌装封尾机-首页-温州精灌 | 乐考网-银行从业_基金从业资格考试_初级/中级会计报名时间_中级经济师 | 美的商用净水器_美的直饮机_一级代理经销商_Midea租赁价格-厂家反渗透滤芯-直饮水批发品牌售后 | 辐射色度计-字符亮度测试-反射式膜厚仪-苏州瑞格谱光电科技有限公司 | 雄松华章(广州华章MBA)官网-专注MBA/MPA/MPAcc/MEM辅导培训 | 泡沫消防车_水罐消防车_湖北江南专用特种汽车有限公司 | 化工ERP软件_化工新材料ERP系统_化工新材料MES软件_MES系统-广东顺景软件科技有限公司 | 禹城彩钢厂_钢结构板房_彩钢复合板-禹城泰瑞彩钢复合板加工厂 | 网站制作优化_网站SEO推广解决方案-无锡首宸信息科技公司 | 下水道疏通_管道疏通_马桶疏通_附近疏通电话- 立刻通 | 美国查特CHART MVE液氮罐_查特杜瓦瓶_制造全球品质液氮罐 | 干法制粒机_智能干法制粒机_张家港市开创机械制造有限公司 | 河南档案架,档案密集架,手动密集架,河南密集架批发/报价 | 丁基胶边来料加工,医用活塞边角料加工,异戊二烯橡胶边来料加工-河北盛唐橡胶制品有限公司 | 北京中创汇安科贸有限公司| 无线联网门锁|校园联网门锁|学校智能门锁|公租房智能门锁|保障房管理系统-KEENZY中科易安 | 桥架-槽式电缆桥架-镀锌桥架-托盘式桥架 - 上海亮族电缆桥架制造有限公司 | 南汇8424西瓜_南汇玉菇甜瓜-南汇水蜜桃价格| 双吸泵,双吸泵厂家,OS双吸泵-山东博二泵业有限公司 | 匀胶机旋涂仪-声扫显微镜-工业水浸超声-安赛斯(北京)科技有限公司 | 自动气象站_农业气象站_超声波气象站_防爆气象站-山东万象环境科技有限公司 | 英语词典_成语词典_日语词典_法语词典_在线词典网 | 板框压滤机-隔膜压滤机-厢式压滤机生产厂家-禹州市君工机械设备有限公司 | 净化车间装修_合肥厂房无尘室设计_合肥工厂洁净工程装修公司-安徽盛世和居装饰 | 苏州注册公司_苏州代理记账_苏州工商注册_苏州代办公司-恒佳财税 |