日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java——聊聊JUC中的线程中断机制 LockSupport

發(fā)布時間:2023/12/16 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java——聊聊JUC中的线程中断机制 LockSupport 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄:

1.什么是中斷機(jī)制?

2.如何停止中斷運(yùn)行中的線程?

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

2.2?通過AtomicBoolean原子布爾類

2.3?通過Thread類自帶的中斷API方法實現(xiàn)

3.Thread類的三大API說明

3.1?實例方法interrupt(),沒有返回值

3.2?實例方法isInterrupted(),返回布爾值

3.3 當(dāng)前線程的中斷標(biāo)識為true,是不是線程就立刻停止?

3.4 在3.3中斷程序的基礎(chǔ)上,添加sleep睡眠

3.5 靜態(tài)方法public static?boolean?interrupted()

4.LockSupport

4.1 線程的等待喚醒機(jī)制

4.2 wait、notify

4.3 await、signal

4.4 park、unpark


1.什么是中斷機(jī)制?

  • 首先,一個線程不應(yīng)該由其他線程來強(qiáng)制中斷或停止,而是應(yīng)該由線程自己自行停止。所以,Thread.stop, Thread.suspend, Thread.resume 都已經(jīng)被廢棄了。
  • 其次,在Java中沒有辦法立即停止一條線程,然而停止線程卻顯得尤為重要,如取消一個耗時操作。

? ? ? ? ? ? ? ? ? 因此,Java提供了一種用于停止線程的協(xié)商機(jī)制——中斷。

? ? ? ? ? ? ? ? ? 中斷只是一種協(xié)作協(xié)商機(jī)制,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)用。

尚硅谷周陽老師的例子:顧客在無煙餐廳中吸煙,服務(wù)員希望他別吸煙了,不是強(qiáng)行停止他吸煙,而是給他的標(biāo)志位打為true,具體的停止吸煙還是要顧客自己停止。(體現(xiàn)了協(xié)商機(jī)制)

  • 中斷相關(guān)的三大API方法如下圖:↓↓↓


2.如何停止中斷運(yùn)行中的線程?

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

package com.szh.demo.interrupt;import java.util.concurrent.TimeUnit;public class InterruptDemo1 {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(Thread.currentThread().getName() + " hello volatile....");}}, "t1").start();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {isStop = true;}, "t2").start();} }

2.2?通過AtomicBoolean原子布爾類

package com.szh.demo.interrupt;import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean;public class InterruptDemo2 {static AtomicBoolean atomicBoolean = new AtomicBoolean(false);public static void main(String[] args) {new Thread(() -> {while (true) {if (atomicBoolean.get()) {System.out.println(Thread.currentThread().getName() + " isStop被修改為true,線程停止");break;}System.out.println(Thread.currentThread().getName() + " hello AtomicBoolean....");}}, "t1").start();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {atomicBoolean.set(true);}, "t2").start();} }

2.3?通過Thread類自帶的中斷API方法實現(xiàn)

package com.szh.demo.interrupt;import java.util.concurrent.TimeUnit;public class InterruptDemo3 {public static void main(String[] args) {Thread t1 = new Thread(() -> {while (true) {if (Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName() + " isStop被修改為true,線程停止");break;}System.out.println(Thread.currentThread().getName() + " hello isInterrupted....");}}, "t1");t1.start();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {t1.interrupt();}, "t2").start();} }


3.Thread類的三大API說明

3.1?實例方法interrupt(),沒有返回值

這個interrupt()實例方法,底層實際上調(diào)用了interrupt0()這個方法,根據(jù)后面的注釋可以看到,僅僅是設(shè)置中斷標(biāo)識位,而interrupt0這個方法是一個native方法,底層又調(diào)用了C。

而在jdk官方文檔中可以看到有關(guān)這個方法的敘述。

3.2?實例方法isInterrupted(),返回布爾值

這個實例方法的底層調(diào)用了一個native方法,傳入了一個布爾值,而這個值就是 是否清除中斷標(biāo)識位,false表示不清除,true表示清除(即將線程的中斷標(biāo)識位清除重新設(shè)置為false)。

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

① 如果線程處于正常活動狀態(tài),那么會將該線程的中斷標(biāo)志設(shè)置為 true,僅此而已。被設(shè)置中斷標(biāo)志的線程將繼續(xù)正常運(yùn)行,不受影響。所以, interrupt() 并不能真正的中斷線程,需要被調(diào)用的線程自己進(jìn)行配合才行。

② 如果線程處于被阻塞狀態(tài)(例如處于sleep, wait, join 等狀態(tài)),在別的線程中調(diào)用當(dāng)前線程對象的interrupt方法,那么線程將立即退出被阻塞狀態(tài)(中斷狀態(tài)將被清除),并拋出一個InterruptedException異常。

(中斷不活動的線程不會產(chǎn)生任何影響,看下面案例)

3.3 當(dāng)前線程的中斷標(biāo)識為true,是不是線程就立刻停止?

  • 否,僅僅設(shè)置了一個中斷狀態(tài)

  • 看看中斷是否會立即停止這個300的線程。否,雖然中斷標(biāo)志位變了。但是i一直輸完300次,才最終停止。

package com.szh.demo.interrupt;import java.util.concurrent.TimeUnit;public class InterruptDemo4 {public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 300; i++) {System.out.println("--------- " + i);}System.out.println("t1調(diào)用interrupt()之后的中斷標(biāo)識02---- " + Thread.currentThread().isInterrupted());}, "t1");t1.start();System.out.println("t1線程默認(rèn)的中斷標(biāo)識---- " + t1.isInterrupted());try {TimeUnit.MILLISECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}t1.interrupt();System.out.println("t1調(diào)用interrupt()之后的中斷標(biāo)識01---- " + t1.isInterrupted());} }

對上面的代碼稍作改變,如下:↓↓↓

package com.szh.demo.interrupt;import java.util.concurrent.TimeUnit;public class InterruptDemo5 {public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 300; i++) {System.out.println("--------- " + i);}System.out.println("after t1.interrupt()---第2次---- " + Thread.currentThread().isInterrupted());}, "t1");t1.start();System.out.println("before t1.interrupt()---- " + t1.isInterrupted());try {TimeUnit.MILLISECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}t1.interrupt();System.out.println("after t1.interrupt()---第1次--- " + t1.isInterrupted());try {TimeUnit.MILLISECONDS.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("after t1.interrupt()---第3次--- " + t1.isInterrupted());} }

在輸出結(jié)果中,我們可以看到和我們預(yù)想的都一樣,只有最后一行輸出,t1線程它自己不是已經(jīng)打斷了嗎?那中斷標(biāo)識就應(yīng)該是 true 啊?為什么變成了false???

原因是上面的代碼中,t1線程打印300次i,而最后一行輸出代碼是在2000ms之后的,t1線程是完全可以在這個時間內(nèi)完成300次i的打印工作,所以程序運(yùn)行到最后一行輸出,t1線程已經(jīng)結(jié)束死亡了,再根據(jù) interrupt 方法api中的這句話:

      • 中斷不存在的線程不需要任何效果。

我們就懂了,中斷不存在的線程沒什么意義的,所以這里的中斷標(biāo)識自然就恢復(fù)成了默認(rèn)值 false。

3.4 在3.3中斷程序的基礎(chǔ)上,添加sleep睡眠

package com.szh.demo.interrupt;import java.util.concurrent.TimeUnit;public class InterruptDemo6 {public static void main(String[] args) {Thread t1 = new Thread(() -> {while (true) {if (Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName() + " 中斷標(biāo)識位:" +Thread.currentThread().isInterrupted() + " 線程終止....");break;}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("---- hello InterruptDemo6");}}, "t1");t1.start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {t1.interrupt();}, "t2").start();} }

這個程序是停不下來的,我是不想耗費(fèi)太多CPU資源,手動停止了。?

原因就是:

      • 如果該線程阻塞的調(diào)用wait() , wait(long) ,或wait(long, int)的方法Object類,或者在join() , join(long) , join(long, int) , sleep(long) ,或sleep(long, int) ,這個類的方法,那么它的中斷狀態(tài)將被清除,并且將收到一個InterruptedException 。

      • 所以這個時候線程t1的中斷標(biāo)識位被清除,恢復(fù)成了false,那么久永遠(yuǎn)也停不下來了。

如何修改上面的代碼,使得程序正常運(yùn)行停止呢?? ?→?

  • 中斷標(biāo)志位 默認(rèn)是false。
  • t2 ----->t1發(fā)出了中斷協(xié)商,t2調(diào)用t1.interrupt(),中斷標(biāo)志位true。
  • 中斷標(biāo)志位true,正常情況下,程序停止。
  • 中斷標(biāo)志位true,異常情況下,InterruptedException,將會把中斷狀態(tài)清除,并且將收到InterruptedException。中斷標(biāo)志位false導(dǎo)致無限循環(huán)。
  • 在catch塊中,需要再次給中斷標(biāo)志位設(shè)置為true,2次調(diào)用停止。
  • package com.szh.demo.interrupt;import java.util.concurrent.TimeUnit;public class InterruptDemo6 {public static void main(String[] args) {Thread t1 = new Thread(() -> {while (true) {if (Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName() + " 中斷標(biāo)識位:" +Thread.currentThread().isInterrupted() + " 線程終止....");break;}try {Thread.sleep(200);} catch (InterruptedException e) {Thread.currentThread().interrupt(); //關(guān)鍵代碼e.printStackTrace();}System.out.println("---- hello InterruptDemo6");}}, "t1");t1.start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {t1.interrupt();}, "t2").start();} }

    3.5 靜態(tài)方法public static?boolean?interrupted()

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

    package com.szh.demo.interrupt;public class InterruptDemo7 {public static void main(String[] args) {System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());System.out.println("-----1");Thread.currentThread().interrupt();//中斷標(biāo)志位設(shè)置為trueSystem.out.println("-----2");System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());} }

    前兩次調(diào)用沒啥說的,因為main主線程并沒有中斷,第三次調(diào)用的時候,因為上面已經(jīng) interrupt 了,所以被中斷了,這里中斷標(biāo)識位肯定就是 true。此時這個靜態(tài)方法在中斷之后第一次調(diào)用(返回當(dāng)前線程的中斷狀態(tài),被中斷了就是true;第二件事,將當(dāng)前線程的中斷標(biāo)識重置為false)。所以當(dāng)最后一行再次調(diào)用它的時候,就是false了。?

    看一下這個靜態(tài)方法的源碼:↓↓↓? ? 在那個isInterrupt實例方法中傳入的 一個布爾值,而這個值就是 是否清除中斷標(biāo)識位,false表示不清除,true表示清除(即將線程的中斷標(biāo)識位清除重新設(shè)置為false)。

    這兩個方法在底層都調(diào)用了native方法isInterrupted。? 只不過傳入?yún)?shù)ClearInterrupted一個傳參傳了true,一個傳了false。

    靜態(tài)方法interrupted() 中true表示清空當(dāng)前中斷狀態(tài)。? 實例方法isInterrupted 則不會。


    4.LockSupport

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

    這個類與每個使用它的線程相關(guān)聯(lián),一個許可證(在Semaphore類的意義上)。 如果許可證可用,則呼叫park將park返回,在此過程中消耗它; 否則可能會阻止。 致電unpark使許可證可用,如果尚不可用。 (與信號量不同,許可證不能累積,最多只有一個。)

    核心就是park()和unpark()方法

    • park()方法是阻塞線程

    • unpark()方法是解除阻塞線程

    4.1 線程的等待喚醒機(jī)制

  • 使用Object中的wait()方法讓線程等待,使用Object中的notify()方法喚醒線程。(有局限性)

  • 使用JUC包中Condition的await()方法讓線程等待,使用signal()方法喚醒線程。(有局限性)

  • LockSupport類可以阻塞當(dāng)前線程以及喚醒指定被阻塞的線程。

  • 4.2 wait、notify

    package com.szh.demo.locksupport;import java.util.concurrent.TimeUnit;public class LockSupportDemo1 {public static void main(String[] args) {final Object obj = new Object();new Thread(() -> {synchronized (obj) {System.out.println(Thread.currentThread().getName() + " --- come in");try {obj.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + " --- 被喚醒了");}, "t1").start();try {TimeUnit.SECONDS.sleep(3L);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {synchronized (obj) {obj.notify();System.out.println(Thread.currentThread().getName() + " --- 發(fā)出通知");}}, "t2").start();} }

    異常情況1:將 synchronized 同步代碼塊對應(yīng)的代碼注釋掉。?

    package com.szh.demo.locksupport;import java.util.concurrent.TimeUnit;public class LockSupportDemo1 {public static void main(String[] args) {final Object obj = new Object();new Thread(() -> {//synchronized (obj) {System.out.println(Thread.currentThread().getName() + " --- come in");try {obj.wait();} catch (InterruptedException e) {e.printStackTrace();}//}System.out.println(Thread.currentThread().getName() + " --- 被喚醒了");}, "t1").start();try {TimeUnit.SECONDS.sleep(3L);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {//synchronized (obj) {obj.notify();System.out.println(Thread.currentThread().getName() + " --- 發(fā)出通知");//}}, "t2").start();} }

    異常情況2:將wait和notify順序調(diào)換。?

    package com.szh.demo.locksupport;import java.util.concurrent.TimeUnit;public class LockSupportDemo1 {public static void main(String[] args) {final Object obj = new Object();new Thread(() -> {try {TimeUnit.SECONDS.sleep(3L);} catch (InterruptedException e) {e.printStackTrace();}synchronized (obj) {System.out.println(Thread.currentThread().getName() + " --- come in");try {obj.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + " --- 被喚醒了");}, "t1").start();// try { // TimeUnit.SECONDS.sleep(3L); // } catch (InterruptedException e) { // e.printStackTrace(); // }new Thread(() -> {synchronized (obj) {obj.notify();System.out.println(Thread.currentThread().getName() + " --- 發(fā)出通知");}}, "t2").start();} }

    小總結(jié)

    • 線程先要獲得并持有鎖,必須在鎖塊(synchronized或lock)中

    • 必須要先等待后喚醒,線程才能夠被喚醒。要保證先wait,后notify才OK。

    • wait和notify方法必須要在同步塊或者方法里面,且成對出現(xiàn)使用。

    4.3 await、signal

    package com.szh.demo.locksupport;import javax.swing.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class LockSupportDemo2 {private static Lock lock = new ReentrantLock();private static Condition condition = lock.newCondition();public static void main(String[] args) {new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + " --- come in");condition.await();System.out.println(Thread.currentThread().getName() + " --- 被喚醒了");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}, "t1").start();try {TimeUnit.SECONDS.sleep(1L);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {lock.lock();try {condition.signal();System.out.println(Thread.currentThread().getName() + " --- 發(fā)出通知");} finally {lock.unlock();}}, "t2").start();} }

    異常情況1:將對應(yīng)的加鎖解鎖的代碼注釋掉,報錯信息和第一個案例是一樣的。?

    異常情況2:先進(jìn)行 signal,再進(jìn)行 await,報錯信息和第一個案例是一樣的。?

    小總結(jié)

    • 線程先要獲得并持有鎖,必須在鎖塊(synchronized或lock)中

    • 必須要先等待后喚醒,線程才能夠被喚醒。一定要先await后signal,不能反了

    • Condition中的線程等待和喚醒方法,需要先獲取鎖

    4.4 park、unpark

    調(diào)用LockSupport.park()時,發(fā)現(xiàn)它調(diào)用了unsafe類,并且默認(rèn)傳了一個0。

    permit默認(rèn)是零,所以一開始調(diào)用park()方法,當(dāng)前線程就會阻塞,直到別的線程將當(dāng)前線程的permit設(shè)置為1時,park方法會被喚醒,然后會將permit再次設(shè)置為零并返回。


    調(diào)用LockSupport.unpark();時,也調(diào)用了unsafe類。

    調(diào)用unpark(thread)方法后,就會將thread線程的許可permit設(shè)置成1(注意多次調(diào)用unpark方法,不會累加,permit值還是1)會自動喚醒thread線程,即之前阻塞中的LockSupport.park()方法會立即返回。

    解決上面兩個案例的第一個問題:必須放在鎖塊中,LockSupport不需要這樣做。?

    package com.szh.demo.locksupport;import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport;public class LockSupportDemo3 {public static void main(String[] args) {Thread t1 = new Thread(() -> {System.out.println(Thread.currentThread().getName() + " --- come in");LockSupport.park();System.out.println(Thread.currentThread().getName() + " --- 被喚醒了");}, "t1");t1.start();try {TimeUnit.SECONDS.sleep(2L);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {LockSupport.unpark(t1);System.out.println(Thread.currentThread().getName() + " --- 發(fā)出通知");}, "t2").start();} }

    解決上面兩個案例的第一個問題:必須先等待,后喚醒,LockSupport不需要這樣做,先喚醒后等待照樣OK。?

    package com.szh.demo.locksupport;import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport;public class LockSupportDemo3 {public static void main(String[] args) {Thread t1 = new Thread(() -> {try {TimeUnit.SECONDS.sleep(3L);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " --- come in " + System.currentTimeMillis());LockSupport.park();System.out.println(Thread.currentThread().getName() + " --- 被喚醒了 " + System.currentTimeMillis());}, "t1");t1.start();new Thread(() -> {LockSupport.unpark(t1);System.out.println(Thread.currentThread().getName() + " --- 發(fā)出通知");}, "t2").start();} }

    這里會先執(zhí)行t2線程的unpark方法,此時t1線程手中就有了一張許可證,當(dāng)t1線程睡眠3秒之后,執(zhí)行代碼,走到park方法不會再阻塞,直接拿出許可證,繼續(xù)向下執(zhí)行,所以看代碼的花費(fèi)時間就知道,這里的park是無效沒有阻塞的。?

    jdk官方文檔中說了,與信號量不同,許可證不能累積,最多只有一個。

    老子就不信這個邪,我非得給你來兩個許可證,看看下面的代碼。

    package com.szh.demo.locksupport;import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport;public class LockSupportDemo3 {public static void main(String[] args) {Thread t1 = new Thread(() -> {try {TimeUnit.SECONDS.sleep(3L);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " --- come in " + System.currentTimeMillis());LockSupport.park();LockSupport.park();System.out.println(Thread.currentThread().getName() + " --- 被喚醒了 " + System.currentTimeMillis());}, "t1");t1.start();new Thread(() -> {LockSupport.unpark(t1);LockSupport.unpark(t1);System.out.println(Thread.currentThread().getName() + " --- 發(fā)出通知");}, "t2").start();} }

    可以看到,代碼卡在這里了,這是因為你雖然發(fā)了兩個許可證,但是最多只能持有一個,那么當(dāng)?shù)诙蝡ark嘗試再去獲取許可證時,已經(jīng)不可能了,因為t1線程手中的那個許可證已經(jīng)被第一次park的時候消費(fèi)掉了。

    當(dāng)調(diào)用park方法時如果有憑證,則會直接消耗掉這個憑證然后正常退出;如果無憑證,就必須阻塞等待憑證可用。

    而unpark則相反, 它會增加一個憑證, 但憑證最多只能有1個, 累加無效。?


    針對park和unpark方法的代碼實測結(jié)論:

  • park:unpark = 1:1,代碼正常執(zhí)行無誤。
  • park:unpark = 1:n,代碼正常執(zhí)行無誤。(盡管unpark了多次,但是當(dāng)前線程最多只能持有1個許可證,之后也只park了一次,消費(fèi)了一個許可證,所以沒問題,但還是不推薦這樣寫)
  • park:unpark = n:1,代碼卡死無法結(jié)束。(當(dāng)前線程最多只能持有1個許可證,park一次消費(fèi)一個,park多次直接無證,當(dāng)前線程無法正常結(jié)束)
  • park:unpark = n:n,代碼卡死無法結(jié)束。(原因在上面說過了)
  • 總結(jié)

    以上是生活随笔為你收集整理的Java——聊聊JUC中的线程中断机制 LockSupport的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。