0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

使用stop、suspend方法來中斷線程的壞處在哪?

Android編程精選 ? 來源:CSDN技術(shù)社區(qū) ? 作者:浪舟子 ? 2021-07-26 14:23 ? 次閱讀

我們知道像stop、suspend這幾種中斷或者阻塞線程的方法在較高java版本中已經(jīng)被標(biāo)記上了@Deprecated過期標(biāo)簽,那么為什么她們曾經(jīng)登上了java的歷史舞臺而又漸漸的推出了舞臺呢,到底是人性的扭曲還是道德的淪喪呢,亦或是她們不思進(jìn)取被取而代之呢,如果是被取而代之,那么取而代之的又是何方人也,本文我們將一探究竟。

一、stop的落幕首先stop方法的作用是什么呢,用java源碼中的一句注釋來了解一下:Forces the thread to stop executing.,即強(qiáng)制線程停止執(zhí)行,‘Forces’似乎已經(jīng)透漏出了stop方法的蠻狠無理。那么我們再看看java開發(fā)者是怎們解釋stop被淘汰了的。

我們從中可以看出以下幾點(diǎn):

stop這種方法本質(zhì)上是不安全的

使用Thread.stop停止線程會導(dǎo)致它解鎖所有已鎖定的監(jiān)視器,即直接釋放當(dāng)前線程已經(jīng)獲取到的所有鎖,使得當(dāng)前線程直接進(jìn)入阻塞狀態(tài)

我們舉例來看一下上邊提到的兩點(diǎn):

public static void main(String[] args) throws InterruptedException {

Object o1=new Object();

Object o2=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

synchronized (o2)

{

try {

System.out.println(“t1獲取到鎖”);

Thread.sleep(5000);

System.out.println(“t1結(jié)束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

t1.start();

Thread.sleep(1000);

Thread t2=new Thread(()-》{

synchronized (o1)

{

synchronized (o2)

{

try {

System.out.println(“t2獲取到鎖”);

Thread.sleep(5000);

System.out.println(“t2結(jié)束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

t2.start();

t1.stop();

}

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

1fb0958c-e009-11eb-9e57-12bb97331649.png

可以看到,當(dāng)線程t1在獲取到o1和o2兩個鎖開始執(zhí)行,在還沒有執(zhí)行結(jié)束的時候,主線程調(diào)用了t1的stop方法中斷了t1的執(zhí)行,釋放了t1線程獲取到的所有鎖,中斷后t2獲取到了o1和o2鎖,開始執(zhí)行直到結(jié)束,而t1卻夭折在了sleep的時候,sleep后的代碼沒有執(zhí)行。

因此使用stop我們在不知道線程到底運(yùn)行到了什么地方,暴力的中斷了線程,如果sleep后的代碼是資源釋放、重要業(yè)務(wù)邏輯等比較重要的代碼的話,亦或是其他線程依賴t1線程的運(yùn)行結(jié)果,那直接中斷將可能造成很嚴(yán)重的后果。

那么不建議使用stop中斷線程我們應(yīng)該怎么去優(yōu)雅的結(jié)束一個線程呢,我們可以存java開發(fā)者的注釋中窺探到一種解決方案:

1fdbe836-e009-11eb-9e57-12bb97331649.png

可以看到j(luò)ava開發(fā)者推薦我們使用以下兩種方法來優(yōu)雅的停止線程:

1.定義一個變量,由目標(biāo)線程去不斷的檢查變量的狀態(tài),當(dāng)變量達(dá)到某個狀態(tài)時停止線程。

代碼舉例如下:

volatile static boolean flag=false;

public static void main(String[] args) throws InterruptedException {

Object o1=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

try {

System.out.println(“t1獲取到鎖”);

while (!flag)

Thread.sleep(5000);//執(zhí)行業(yè)務(wù)邏輯

System.out.println(“t1結(jié)束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

t1.start();

Thread.sleep(1000);

Thread t2=new Thread(()-》{

synchronized (o1)

{

try {

System.out.println(“t2獲取到鎖”);

Thread.sleep(5000);//執(zhí)行業(yè)務(wù)邏輯

System.out.println(“t2結(jié)束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

t2.start();

flag=true;

}

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

1ffacdc8-e009-11eb-9e57-12bb97331649.png

2.使用interrupt方法中斷線程。

代碼舉例如下:

public static void main(String[] args) throws InterruptedException {

Object o1=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

System.out.println(“t1獲取到鎖”);

while (!Thread.currentThread().isInterrupted()) {

for (int i = 0; i 《 100; i++) {

if(i==50)

System.out.println();

System.out.print(i+“ ”);

}

System.out.println();

}

System.out.println(“t1結(jié)束”);

}

});

t1.start();

Thread t2=new Thread(()-》{

synchronized (o1)

{

try {

System.out.println(“t2獲取到鎖”);

Thread.sleep(5000);//執(zhí)行業(yè)務(wù)邏輯

System.out.println(“t2結(jié)束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

t2.start();

t1.interrupt();

}

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

202dbdb4-e009-11eb-9e57-12bb97331649.png

我們用while (!Thread.currentThread().isInterrupted())來不斷判斷當(dāng)前線程是否被中斷,中斷的話則讓線程自然消亡并釋放鎖??梢钥吹秸{(diào)用interrupt方法后并不會像stop那樣暴力的中斷線程,會等到當(dāng)前運(yùn)行的邏輯結(jié)束后再檢查是否中斷,非常的優(yōu)雅。另外,關(guān)注Java知音公眾號,回復(fù)“后端面試”,送你一份面試題寶典!

注:運(yùn)行舉例代碼可能不會打印出數(shù)字,這是因?yàn)閠1線程運(yùn)行到while(!Thread.currentThread().isInterrupted())時,主線程已經(jīng)調(diào)了interrupt方法,因此多次運(yùn)行可能會打印出數(shù)字。

二、suspend的落幕suspend方法的作用是掛起某個線程直到調(diào)用resume方法來恢復(fù)該線程,但是調(diào)用了suspend方法后并不會釋放被掛起線程獲取到的鎖,正因如此就給suspend和resume這哥倆貼上了容易引發(fā)死鎖的標(biāo)簽,當(dāng)然這也正是導(dǎo)致suspend和resume退出歷史舞臺的罪魁禍?zhǔn)住M瑯游覀兛纯磈ava開發(fā)者為suspend的淘汰給出的理由:

206731fc-e009-11eb-9e57-12bb97331649.png

從中我們可以得出以下結(jié)論:

suspend具有天然的死鎖傾向

當(dāng)某個線程被suspend后,該線程持有的鎖不會被釋放,其他線程也就不能訪問這些資源

suspend某個線程后,如果在resume的過程中出現(xiàn)異常導(dǎo)致resume方法執(zhí)行失敗,則lock無法釋放,導(dǎo)致死鎖

接下來模擬一下由suspend引起的死鎖場景,Talk is cheap,show my code:

public static void main(String[] args) throws InterruptedException {

Object o1=new Object();

Object o2=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

System.out.println(“t1獲取到o1鎖開始執(zhí)行”);

try {

Thread.sleep(5000);//模擬執(zhí)行業(yè)務(wù)邏輯

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“t1執(zhí)行結(jié)束”);

}

});

t1.start();

Thread t2=new Thread(()-》{

synchronized (o2)

{

System.out.println(“t2獲取到o2開始執(zhí)行”);

try {

Thread.sleep(2000);//執(zhí)行耗時業(yè)務(wù)

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (o1)

{

System.out.println(“t2獲取到o1鎖開始繼續(xù)執(zhí)行”);

}

System.out.println(“t2執(zhí)行結(jié)束”);

}

});

t2.start();

Thread.sleep(1000);

t1.suspend();

//假設(shè)拋出了一個未知異常

int i=1/0;

t1.resume();

}

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

20736242-e009-11eb-9e57-12bb97331649.png

可以看到,整個程序卡的死死的,在調(diào)用resume恢復(fù)t1線程之前拋出了一個未知異常,導(dǎo)致t1一直掛起進(jìn)而無法釋放o1鎖,而t2需要獲取到o1鎖后才能繼續(xù)執(zhí)行,但苦苦等待,奈何o1被t1拿捏的死死的,從此整個程序就陷入了無盡的等待中----死鎖。

作者丨浪舟子

blog.csdn.net/qq_40400960/article/details/112651249

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    894

    瀏覽量

    41326

原文標(biāo)題:為什么強(qiáng)烈不推薦使用stop、suspend方法來中斷線程?

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    控制回路斷線可能原因及如何處理

    控制回路斷線是電氣系統(tǒng)中常見的故障之一,它可能導(dǎo)致設(shè)備無法正常工作,甚至引發(fā)安全事故。本文將分析控制回路斷線的可能原因,并提出相應(yīng)的處理方法。 一、控制回路斷線的可能原因 接線錯誤 接
    的頭像 發(fā)表于 08-23 16:36 ?1021次閱讀

    armv8在啟動剛開始時調(diào)用了關(guān)中斷,一直到切換第一個線程,在哪里開啟的中斷呢?

    例如當(dāng)前使用的armv8芯片,在啟動剛開始時調(diào)用了關(guān)中斷,一直到切換第一個線程,在哪里開啟的中斷呢? int rtthread_startup(void
    發(fā)表于 07-04 07:00

    AD8338有沒有可行的方法來測量大增益?

    AD8338是一款VGA芯片,可變增益范圍為-10dB至70dB。然而,理論上的70dB增益過大,導(dǎo)致來自源的輸入信號非常小,容易受到干擾,導(dǎo)致70dB增益未得到驗(yàn)證。有沒有可行的方法來測量大增益?
    發(fā)表于 05-21 07:06

    STM32F107的OTG在stop模式下無法通過EXTI_18喚醒,沒有中斷產(chǎn)生是怎么回事?

    作為device,想驗(yàn)證EXTI_18的中斷,配置好EXTI初始化,但只有在enable suspend int后,在插拔USB線纜時才會進(jìn)OTG_FS_WKUP_IRQHandler,如果配置設(shè)備
    發(fā)表于 05-06 08:59

    使用FreeRTOS創(chuàng)建的DHCP線程里面的DHCP是在哪里定義的?

    請教下,使用 FreeRTOS 創(chuàng)建的 DHCP 線程里面的 DHCP 是在哪里定義的,貌似沒有找到 ? FreeRTOS 版本 v9.0.0 具體如下: // 創(chuàng)建 DHCP 線程 void
    發(fā)表于 04-30 07:34

    stm32外部中斷不能喚醒stop休眠模式怎么解決?

    按鍵引腳設(shè)置成外部中斷方式,可以正常喚醒stop模式;但是充電口設(shè)置成外部中斷,卻無法喚醒stop休眠?。?!配置都是一樣的,按鍵下降沿觸發(fā),充電檢測是上升沿觸發(fā)。 有可能是什么原因,
    發(fā)表于 04-26 06:11

    如果是使用六步方波的方法來控制電機(jī),要如何實(shí)現(xiàn)過電流保護(hù)?

    請問一下如果是使用六步方波的方法來控制電機(jī),要如何實(shí)現(xiàn)過電流保護(hù)? 以免電流過大造成板子損壞
    發(fā)表于 04-22 08:10

    加濕器的作用及好處與壞處 加濕器的正確使用方法

    疾病的發(fā)生。然而,過度使用加濕器或錯誤使用也可能會導(dǎo)致空氣中的細(xì)菌和霉菌增加,對健康產(chǎn)生負(fù)面影響。以下是關(guān)于加濕器的作用及好處與壞處以及正確使用方法。 加濕器的作用及好處: 改善干燥環(huán)境:加濕器能夠在干燥環(huán)境
    的頭像 發(fā)表于 01-25 09:52 ?1304次閱讀

    火線斷線和零線斷線的危害

    在我們?nèi)嗨木€的供電回路里,三根火線和一根零線都是不能缺少的,任何一根斷線都會給我們的用電設(shè)備造成嚴(yán)重的危害,那么火線斷線和零線斷線的造成后果是一樣的嗎?
    的頭像 發(fā)表于 01-17 10:02 ?2445次閱讀
    火線<b class='flag-5'>斷線</b>和零線<b class='flag-5'>斷線</b>的危害

    PT斷線是什么?為什么說PT斷線影響很嚴(yán)重?

    PT斷線是什么?為什么說PT斷線影響很嚴(yán)重? PT斷線是指電壓互感器的一種故障狀態(tài),即PT缺乏或中斷了電壓信號的傳輸。PT作為一種重要的電氣元件,主要用于將高壓系統(tǒng)的電壓降到安全范圍內(nèi)
    的頭像 發(fā)表于 12-26 16:01 ?2709次閱讀

    一種簡單的方法來將振蕩器相位噪聲轉(zhuǎn)換為時間抖動

    電子發(fā)燒友網(wǎng)站提供《一種簡單的方法來將振蕩器相位噪聲轉(zhuǎn)換為時間抖動.pdf》資料免費(fèi)下載
    發(fā)表于 11-23 15:15 ?0次下載
    一種簡單的<b class='flag-5'>方法來</b>將振蕩器相位噪聲轉(zhuǎn)換為時間抖動

    線程同步的幾種方法

    線程同步是指在多個線程并發(fā)執(zhí)行的情況下,為了保證線程執(zhí)行的正確性和一致性,需要采用特定的方法來協(xié)調(diào)線程之間的執(zhí)行順序和共享資源的訪問。下面
    的頭像 發(fā)表于 11-17 14:16 ?1055次閱讀

    如何使用硬件FIFO減少接收中斷次數(shù)

    本文給介紹如何使用帶FIFO的串口減少接收中斷次數(shù),通過一種自定義通訊協(xié)議格式,給出幀打包方法;之后介紹一種特殊的串口數(shù)據(jù)發(fā)送方法,可在避免使用串口發(fā)送
    發(fā)表于 11-06 12:22 ?507次閱讀
    如何使用硬件FIFO<b class='flag-5'>來</b>減少接收<b class='flag-5'>中斷</b>次數(shù)

    中斷嵌套的好處與壞處有哪些?

    中斷嵌套的好處與壞處有哪些
    發(fā)表于 10-27 06:44

    STM32如何配置外部中斷?STM32外部中斷配置步驟

    觸發(fā)或上升沿觸發(fā)的外部中斷線。這些中斷線可以通過中斷線控制器(EXTI)進(jìn)行設(shè)置,并可以綁定到不同的GPIO端口上,以實(shí)現(xiàn)
    的頭像 發(fā)表于 10-26 17:47 ?3234次閱讀