欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的線程中斷機制和LockSupport詳解

 更新時間:2023年09月26日 11:14:42   作者:苦 糖 果  
這篇文章主要介紹了Java中的線程中斷機制和LockSupport詳解,在Java中沒有辦法立即停止一條線程,然而停止線程卻顯得尤為重要,如取消一個耗時操作,因此,Java提供了一種用于停止線程的協(xié)商機制中斷,也即中斷標(biāo)識協(xié)商機制,需要的朋友可以參考下

線程中斷機制

線程中斷機制概念

首先,一個線程不應(yīng)該由其他線程來強制中斷或停止,而是應(yīng)該由線程自己自行停止,自己來決定自己的命運。所以,Thread.stop, Thread.suspend, Thread.resume 都已經(jīng)被廢棄了。

其次,在Java中沒有辦法立即停止一條線程,然而停止線程卻顯得尤為重要,如取消一個耗時操作。因此,Java提供了一種用于停止線程的協(xié)商機制―—中斷,也即中斷標(biāo)識協(xié)商機制。

中斷只是一種協(xié)作協(xié)商機制,Java沒有給中斷增加任何語法,中斷的過程完全需要程序員自己實現(xiàn)。 若要中斷一個線程,你需要手動調(diào)用該線程的interrupt方法,該方法也僅僅是將線程對象的中斷標(biāo)識設(shè)成true;接著你需要自己寫代碼不斷地檢測當(dāng)前線程的標(biāo)識位,如果為true,表示別的線程請求這條線程中斷,此時究竟該做什么需要你自己寫代碼實現(xiàn)。

每個線程對象中都有一個中斷標(biāo)識位,用于表示線程是否被中斷;該標(biāo)識位為true表示中斷,為false表示未中斷;通過調(diào)用線程對象的interrupt方法將該線程的標(biāo)識位設(shè)為true;可以在別的線程中調(diào)用,也可以在自己的線程中調(diào)用。

常用API

public void interrupt()

實例方法,Just to set the interrupt flag 實例方法interrupt()僅僅是設(shè)置線程的中斷狀態(tài)為true,發(fā)起一個協(xié)商而不會立刻停止線程

public static boolean interrupted()

靜態(tài)方法,Thread.interrupted();判斷線程是否被中斷并清除當(dāng)前中斷狀態(tài)。這個方法做了兩件事: 返回當(dāng)前線程的中斷狀態(tài),測試當(dāng)前線程是否已被中斷 將當(dāng)前線程的中斷狀態(tài)清零并重新設(shè)為false,清除線程的中斷狀態(tài) 此方法有點不好理解,如果連續(xù)兩次調(diào)用此方法,則第二次調(diào)用將返回false,因為連續(xù)調(diào)用兩次的結(jié)果可能不一樣

中斷標(biāo)識被清空,如果該方法被連續(xù)調(diào)用兩次,第二次調(diào)用將返回false 除非當(dāng)前線程在第一次和第二次調(diào)用該方法之間再次被interrupt

public boolean isInterrupted()

實例方法,判斷當(dāng)前線程是否被中斷(通過檢查中斷標(biāo)志位)

interrupted()與isInterrupted()的區(qū)別

在這里插入圖片描述

方法的注釋也清晰的表達了“中斷狀態(tài)將會根據(jù)傳入的ClearInterrupted參數(shù)值確定是否重置“ 所以,靜態(tài)方法interrupted將會清除中斷狀態(tài)(傳入的參數(shù)ClearInterrupted為true) , 實例方法isInterrupted則不會(傳入的參數(shù)ClearInterrupted為false)。

如何停止中斷運行中的線程?

通過一個volatile變量實現(xiàn)

private static volatile boolean isStop = false;
 public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                if (isStop) {
                    System.out.println(Thread.currentThread().getName() + "線程isStop = true,自己退出");
                    break;
                }
                System.out.println("-------hello interrupt--------");
            }
        }, "t1").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        isStop = true;
    }

通過AtomicBoolean

private static final AtomicBoolean atomicBoolean = new AtomicBoolean(true);
    public static void main(String[] args) {
        new Thread(() -> {
            while (atomicBoolean.get()) {
                try {
                    TimeUnit.MILLISECONDS.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("-------hello------");
            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        atomicBoolean.set(false);
    }

通過Thread類自帶的中斷api實例方法實現(xiàn)

public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("-----t1 線程被中斷了,程序結(jié)束");
                    break;
                }
                System.out.println("-----hello-------");
            }
        }, "t1");
        t1.start();
        System.out.println("t1是否被中斷:" + t1.isInterrupted());
        try {
            TimeUnit.MILLISECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
        System.out.println("t1是否被中斷:" + t1.isInterrupted());
    }

在需要中斷的線程中不斷監(jiān)聽中斷狀態(tài),一旦發(fā)生中斷,就執(zhí)行相應(yīng)的中斷處理業(yè)務(wù)邏輯stop線程

具體來說,當(dāng)對一個線程,調(diào)用interrupt()時:

  • 如果線程處于正?;顒訝顟B(tài),那么會將該線程的中斷標(biāo)志設(shè)置為 true,僅此而已。被設(shè)置中斷標(biāo)志的線程將繼續(xù)正常運行,不受影響。所以,interrupt()并不能真正的中斷線程,需要被調(diào)用的線程自己進行配合才行。
  • 如果線程處于被阻塞狀態(tài)(例如處于sleep, wait, join等狀態(tài)),在別的線程中調(diào)用當(dāng)前線程對象的interrupt方法,那么線程將立即退出被阻塞狀態(tài),并拋出一個InterruptedException異常。在catch塊中應(yīng)該加上一行代碼:Thread.currentThread().interrupt(); 為什么要寫這個? 這是維持狀態(tài)。sleep(),wait()方法拋出InterruptException異常后會清除中斷標(biāo)志,即把中斷標(biāo)志設(shè)為false。而你又捕獲了InterruptException,這時你基本上阻止任何更高級別的方法/線程組注意到中斷。這可能會導(dǎo)致問題。通過調(diào)用Thread.currentThread().interrupt(),你可以設(shè)置線程的中斷標(biāo)志(即把中斷標(biāo)志設(shè)為true),因此更高級別的中斷處理程序會注意到它并且可以正確處理它。

當(dāng)前線程的中斷標(biāo)識為true,是不是線程就立刻停止? 實例方法interrupt()僅僅是設(shè)置線程的中斷狀態(tài)位為true,不會停止線程。中斷只是一種協(xié)商機制,修改中斷標(biāo)識位僅此而已,不是立刻stop打斷

sleep方法拋出InterruptedException后,中斷標(biāo)識也被清空置為false,我們在catch沒有通過調(diào)用th.interrupt()方法再次將中斷標(biāo)識置為true,這就導(dǎo)致無限循環(huán)了

LockSupport

LockSupport初探

LockSupport是用來創(chuàng)建鎖和其他同步類的基本線程阻塞原語。

LockSupport中的park()和 unpark()的作用分別是阻塞線程和解除阻塞線程

LockSupport類中的park等待和unpark喚醒 LockSupport類使用了一種名為Pemit(許可)的概念來做到阻塞和喚醒線程的功能,每個線程都有一個許可(permit), 但與Semaphore不同的是,許可的累加上限是1。 permit許可證默認(rèn)沒有不能放行,所以一開始調(diào)park()方法當(dāng)前線程就會阻塞,直到別的線程給當(dāng)前線程的發(fā)放permit,park方法才會被喚醒。 調(diào)用unpark(thread)方法后,就會將thread線程的許可證permit發(fā)放,會自動喚醒park線程,即之前阻塞中的LockSuppot.pak()方法會立即返回。

線程等待喚醒機制

3種讓線程等待和喚醒的方法

  • 方式1:使用object中的wait()方法讓線程等待,使用Object中的notify()方法喚醒線程
  • 方式2:使用Juc包中Condition的await()方法讓線程等待,使用signal()方法喚醒線程
  • 方式3:LockSupport類可以阻塞當(dāng)前線程以及喚醒指定被阻塞的線程

上述兩個對象object和Condition使用的限制條件 線程先要獲得并持有鎖,必須在鎖塊(synchronized或lock)中 必須要先等待后喚醒,線程才能夠被喚醒

LockSupport優(yōu)勢 正常+無鎖塊要求 之前錯誤的先喚醒后等待,LockSupport照樣支持

為什么可以突破wait/notify的原有調(diào)用順序? 因為unpark獲得了一個憑證,之后再調(diào)用park方法,就可以名正言順的憑證消費,故不會阻塞。先發(fā)放了憑證后續(xù)可以暢通無阻。

為什么喚醒兩次后阻塞兩次,但最終結(jié)果還會阻塞線程? 因為憑證的數(shù)量最多為1,連續(xù)調(diào)用兩次unpark和調(diào)用一次 unpark效果一樣,只會增加一個憑證;而調(diào)用兩次park卻需要消費兩個憑證,杯夠,不能放行

LockSupport總結(jié):

LockSupport是用來創(chuàng)建鎖和其他同步類的基本線程阻塞原語。 LockSupport是一個線程阻塞工具類,所有的方法都是靜態(tài)方法,可以讓線程在任意位置阻塞,阻塞之后也有對應(yīng)的喚醒方法。歸根結(jié)底,LockSupport調(diào)用的Unsafe中的native代碼。

LockSupport提供park()和unpark()方法實現(xiàn)阻塞線程和解除線程阻塞的過程LockSupport和每個使用它的線程都有一個許可(permit)關(guān)聯(lián)。每個線程都有一個相關(guān)的permit, permit最多只有一個,重復(fù)調(diào)用unpark也不會積累憑證。

線程阻塞需要消耗憑證(permit),這個憑證最多只有1個。當(dāng)調(diào)用park方法時如果有憑證,則會直接消耗掉這個憑證然后正常退出;如果無憑證,就必須阻塞等待憑證可用;而unpark則相反,它會增加一個憑證,但憑證最多只能有1個,累加無效。

到此這篇關(guān)于Java中的線程中斷機制和LockSupport詳解的文章就介紹到這了,更多相關(guān)Java線程中斷機制和LockSupport內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springBoot @Enable* 注解的使用

    springBoot @Enable* 注解的使用

    這篇文章主要介紹了springBoot @Enable* 注解的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • springboot zuul實現(xiàn)網(wǎng)關(guān)的代碼

    springboot zuul實現(xiàn)網(wǎng)關(guān)的代碼

    這篇文章主要介紹了springboot zuul實現(xiàn)網(wǎng)關(guān)的代碼,在為服務(wù)架構(gòu)體系里,網(wǎng)關(guān)是非常重要的環(huán)節(jié),他實現(xiàn)了很多功能,具體哪些功能大家跟隨小編一起通過本文學(xué)習(xí)吧
    2018-10-10
  • Java語言實現(xiàn)簡單FTP軟件 FTP連接管理模塊實現(xiàn)(8)

    Java語言實現(xiàn)簡單FTP軟件 FTP連接管理模塊實現(xiàn)(8)

    這篇文章主要為大家詳細(xì)介紹了Java語言實現(xiàn)簡單FTP軟件,F(xiàn)TP連接管理模塊的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Apache CXF如何把wsdl生成java代碼

    Apache CXF如何把wsdl生成java代碼

    這篇文章主要介紹了Apache CXF如何把wsdl生成java代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • SpringBoot全局處理統(tǒng)一返回類型方式

    SpringBoot全局處理統(tǒng)一返回類型方式

    這篇文章主要介紹了SpringBoot全局處理統(tǒng)一返回類型方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • MyBatis實現(xiàn)模糊查詢的幾種方式

    MyBatis實現(xiàn)模糊查詢的幾種方式

    這篇文章主要介紹了MyBatis實現(xiàn)模糊查詢的幾種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 淺談java中replace()和replaceAll()的區(qū)別

    淺談java中replace()和replaceAll()的區(qū)別

    這篇文章主要介紹了java中replace()和replaceAll()的區(qū)別,兩者都是常用的替換字符的方法,感興趣的小伙伴們可以參考一下
    2015-11-11
  • Java時間處理第三方包Joda?Time使用詳解

    Java時間處理第三方包Joda?Time使用詳解

    這篇文章主要為大家介紹了Java時間處理第三方包Joda?Time使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Springboot2 集成 druid 加密數(shù)據(jù)庫密碼的配置方法

    Springboot2 集成 druid 加密數(shù)據(jù)庫密碼的配置方法

    這篇文章給大家介紹Springboot2 集成 druid 加密數(shù)據(jù)庫密碼的配置方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-07-07
  • java多態(tài)注意項小結(jié)

    java多態(tài)注意項小結(jié)

    面向?qū)ο蟮娜筇匦裕悍庋b、繼承、多態(tài)。從一定角度來看,封裝和繼承幾乎都是為多態(tài)而準(zhǔn)備的。今天通過本文給大家介紹java多態(tài)注意項總結(jié),感興趣的朋友一起看看吧
    2021-10-10

最新評論