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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

full outer join 与full join的区别_sleep、yield、join都是干啥的? sleep与wait有啥区别?中篇[十五]...

發布時間:2024/7/23 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 full outer join 与full join的区别_sleep、yield、join都是干啥的? sleep与wait有啥区别?中篇[十五]... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方?“?布衣碼農?”?,免費訂閱~選擇“?設為星標?”,第一時間免費獲得更新~

「布衣碼農」用不到卻又不得不學習了解的底層方法+1。Object中的wait、notify、notifyAll,可以用于線程間的通信,核心原理為借助于監視器的入口集與等待集邏輯。通過這三個方法完成線程在指定鎖(監視器)上的等待與喚醒,這三個方法是以鎖(監視器)為中心的通信方法 。除了他們之外,還有用于線程調度、控制的方法,他們是sleep、yield、join方法,他們也可以用于線程的協作,他們是圍繞著線程的調度而來的 。

sleep方法

有兩個版本的sleep方法,看得出來,核心仍舊是native方法。非native方法只是進行了參數校驗,接著仍舊是調用的native方法,這個情形與wait是類似的接下來仔細看下,native版本的sleep在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響。該線程不丟失任何監視器的所屬權。注意:sleep不會釋放鎖,不會釋放鎖,不會釋放鎖!!!可以理解為他進入監視器這個房間之后,在這房間里面睡著了。與wait類似的是,sleep也是可中斷方法(從方法簽名可以看得出來,可能拋出InterruptedException),也就是說如果一個線程正在sleep,如果另外的線程將他中斷(調用interrupt方法),將會拋出異常,并且中斷狀態將會擦除。所以對于sleep方法,要么自己醒來,要么被中斷后也會醒來。對于sleep始終有一個超時時間的設置,所以,盡管他是在監視器內睡著了,但是并不會導致死鎖,因為他終究是要醒來的。如下,線程休眠500毫秒,主線程50毫秒打印一次狀態ps:sleep方法的調用結果為狀態:TIMED_WAITING借助于sleep方法,可以模擬線程的順序執行比如下面示例,兩個階段,第二個階段將在第一個階段執行之后才會執行package test1;import java.lang.Thread.State;public class T16 {public static void main(String[] args) { //模擬執行任務的第一個階段的執行 Thread stepOne = new Thread(() -> { System.out.println(Thread.currentThread().getName()+" : 第一階段任務開始執行"); try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+" : 第一階段任務執行結束"); } catch (InterruptedException e) { } }, "firstStage"); stepOne.start(); //模擬任務第二個階段的執行 Thread stepTwo = new Thread(() -> { while (!State.TERMINATED.equals(stepOne.getState())) { try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+" : 我在等待第一階段任務執行結束"); } catch (InterruptedException e) { } } System.out.println(Thread.currentThread().getName()+" : 第二階段任務執行結束"); }, "secondStage"); stepTwo.start(); }}另外,你應該已經注意到sleep方法都有static修飾,既然是靜態方法,在Thread中的慣例就是針對于:當前線程,當前線程,當前線程!

yield方法

對于sleep或者wait方法,他們都將進入特定的狀態,伴隨著狀態的切換,也就意味著等待某些條件的發生,才能夠繼續,比如條件滿足,或者到時間等。但是yield方法不涉及這些事情,他針對的是時間片的劃分與調度,所以對開發者來說只是臨時讓一下,讓一下他又不會死,就只是再等等yield方法將會暫停當前正在執行的線程對象,并執行其他線程,他始終都是RUNNABLE狀態不過要注意,可以認為yield只是一種建議性的,如果調用了yield方法,對CPU時間片的分配進行了“禮讓”,他仍舊有可能繼續獲得時間片,并且繼續執行。所以一次調用yield 并不一定會代表肯定會發生什么。借助于while循環以及yield方法,也能一定程度上達到線程排序等待的效果yield也是靜態方法,所以,也是針對于當前線程,當前線程,當前線程。

join方法

三個版本的join方法方法的實現過程,與wait也是非常類似,下面兩個版本的方法一個調用join(0),一個參數校驗后,調用join(millis),所以根本還是單參數版本的join方法在方法深入介紹前先看個例子一個線程,循環5次,每次sleep 1s,主線程中打印信息從結果可以看到,主線程總是在線程執行之后,才會執行。也就是主線程在等待我們創建的這個線程結束,結束了之后才會繼續進行如果調整下順序--->start 與 join的先后順序,再次看下情況,可以發現順序沒有保障了結論:主線程main中調用啟動線程(調用start),然后調用該線程的join方法,可以達到主線程等待工作線程運行結束才執行的效果,并且join要在start調用后如何做到的?從上面源代碼可以看得出來,內部調用了wait方法,所以也能明白為啥join也會拋出InterruptedException了吧主線程main中調用thread.join()方法,join方法相當于join(0),也就是 while (isAlive()) { wait(0); }而這個wait(0)就相當于是this.wait(0),this就是我們自己創建的那個線程thread,看看方法的簽名是不是有一個synchronized。isAlive()也是this.isAlive(),也就是如果當前線程alive(已經啟動,但是未終止),那么將持續等待,等待的臨界資源就是我們創建的這個線程對象本身。所以這兩行代碼的含義就是:該線程是否還存活?如果存活,調用join的那個線程將會在這個對象上進行等待(進入該線程對象的等待集)也就是說調用一個線程的join方法,就是在這個線程是等待,這個線程對象就是我們的鎖對象(不要疑惑,Object都可以作為鎖,Thread實例對象怎么不可以?)肯定大家很奇怪,既然是等待,wait又不會自己醒來,那不是出問題了嗎?其實線程結束后,會調用this.notifyAll,所以主線程main會被喚醒如果傳遞的參數不為0,將會走到下面的分支,會wait指定時長,與上面的邏輯一致,只不過是有指定超時時長而已 long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base;手動版本的等待結束只是將join方法換成了同步代碼塊,鎖對象為那個線程的實例對象thread,調用他的wait方法從結果上看,效果一樣(不過此處沒有持續監測isAlive(),所以一旦主線程醒來,即使線程沒有結束,也會繼續,不能百分百確保main肯定等待線程結束)不過要注意:注釋中有說明,自己不要使用Thread類的實例對象作為鎖對象,如果是現在這種場景,使用join即可為什么?從目前來看,join方法就是以這個對象為鎖,如果你自己在使用,又是wait又是notify(notifyAll)的,萬一出現什么隱匿的問題咋辦?所以join方法的原理就是:將指定的Thread實例對象作為鎖對象,在其上進行同步,只要那個線程還活著,那么就會持續等待(或者有限時長)。線程終止之后會調用自身this.notifyAll,以通知在其上等待的線程。簡單說,只要他活著大家就都等著, 他死了會通知,所以效果就是在哪里調用了誰的join,哪里就要等待這個線程結束,才能繼續。為什么要在start之后?如上面所示,將join改造成同步代碼塊如下所示,如果這段同步代碼在start方法之前看下結果,沒有等待指定線程結束,main主線程就結束了因為如果還沒有調用start方法,那么isAlive是false(已開始未結束),主線程根本就不會等待,所以繼續執行,然后繼續到下面的start,然后主線程結束。所以,為什么join方法一定要在start之前?就是因為這個isAlive方法的校驗,你沒有start,isAlive就是false,就不會同步等待,所以必須要先start,然后才能join小結:對于join方法,有兩個關鍵:
  • 調用的哪個對象的join?

  • 在哪里調用的?

換一個說法:join的效果是:一個線程等待另一個線程(直到結束或者持續一段時間)才執行,那么誰等待誰?在哪個線程調用,哪個線程就會等待;調用的哪個Thread對象,就會等待哪個線程結束;

狀態圖回顧

在回顧下之前狀態一文中的切換圖,又了解了這幾個方法后,應該對狀態切換有了更全面的認識

總結

對于yield方法,比較容易理解,只是簡單地對于CPU時間片的“禮讓”,除非循環yield,否則一次yield,可能下次該線程仍舊可能會搶占到CPU時間片,可能方法調用和不調用沒差別。sleep是靜態方法,針對當前線程,進入休眠狀態,兩個版本的sleep方法始終有時間參數,所以必然會在指定的時間內蘇醒,他也不會釋放鎖,當然,sleep方法的調用不是必須在同步方法(同步代碼塊)內。join是實例方法,表示等待誰,是用于線程順序的調度方法,可以做到一個線程等待另外一個線程,join有三個版本,指定超時時間或者持續等待直到目標線程執行結束,join也無需在同步方法(同步代碼塊)內。sleep和join都是可中斷方法,被其他線程中斷時,都會拋出InterruptedException異常,并且會醒來join方法底層依賴wait,我們對比下wait與sleep?
  • wait和sleep都會使線程進入阻塞狀態,都是可中斷方法,被中斷后都會拋出異常

  • wait是Object的方法,sleep是Thread的方法

  • wait必須在同步中執行,sleep不需要(join底層依賴wait,但是不需要在同步中,因為join方法就是synchronized的)

  • wait會釋放鎖,sleep不會釋放鎖

  • wait(無超時設置的版本)會持續阻塞,必須等待喚醒,而sleep必然有超時,所以一定會自己醒來

  • wait 實例方法(Object),在對象上調用,表示在其上等待;sleep靜態方法,當前線程??

··················END··················

注:非技術講解配圖均來源于網絡

期待分享

如果對你有用

可以點個?「在看」?或者分享到?「?朋友圈?」?哦

你「在看」嗎??↓↓

總結

以上是生活随笔為你收集整理的full outer join 与full join的区别_sleep、yield、join都是干啥的? sleep与wait有啥区别?中篇[十五]...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。