分享Java線程的生命週期

Java線程的生命週期 spa

一個線程的產生是從咱們調用了start方法開始進入Runnable狀態,便可以被調度運行狀態,並無真正開始運行,調度器能夠將CPU分配給它,使線程進入Running狀態,真正運行其中的程序代碼。線程在運行過程當中,有如下幾個可能的去向: 線程

(1)調度器在某個線程的執行過程當中將CPU分配給了其它線程,則這個線程又變爲Runnable狀態,等待被調度。 對象

(2)調度器將CPU分配給了該線程,執行過程當中沒有遇到任何阻隔,運行完成直接結束,也就是run()方法執行完畢。 生命週期

(3)線程在執行過程當中請求鎖,卻得不到,這時候它要進入lock pool中等待對象的鎖,等到鎖後又會進入Runnable狀態,能夠被調度運行。 it

(4)線程在執行過程當中遇到wait()方法,它會被放入wait pool中等待,直到有notify()或interrupt()方法執行,它纔會被喚醒或打斷進入lock pool開始等待對象鎖,等到鎖後進入Runnable狀態。 io

推薦在run方法中使用控制循環條件的方式來結束一個線程。 循環

wait:告訴當前線程放棄對象鎖並進入等待狀態,直到其餘線程進入同一對象鎖並調用notify爲止。 yield

notify:喚醒同一對象鎖中調用wait的第一個線程。 請求

notifyAll:喚醒同一對象鎖中調用wait的全部線程,具備最高優先級的線程首先被喚醒並執行。 程序

yield:若是知道已經完成了在run()方法的循環的一次迭代過程當中所須要的工做,就能夠給線程調度一個機制暗示:個人工做已經作的差很少了,可讓給別的線程使用CPU了。經過調用yield()來實現。
當調用yield時,你也是在建議具備相同優先級的其餘線程能夠運行。
對於任何重要的控制或在調整應用時,都不恩那個依賴於yield。實際上,yield常常被誤用。
(yield並不意味着退出和暫停,只是,告訴線程調度若是有人須要,能夠先拿去,我過會再執行,沒人須要,我繼續執行)
調用yield的時候鎖並無被釋放。

interrupt簡述

interrupt()方法只是改變中斷狀態而已,它不會中斷一個正在運行的線程。這一方法實際完成的是,給受阻塞的線程發出一箇中斷信號,這樣受阻線程就得以退出阻塞的狀態。更確切的說,若是線程被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,此時調用該線程的interrupt()方法,那麼該線程將拋出一個InterruptedException中斷異常(該線程必須事先預備好處理此異常),從而提前地終結被阻塞狀態。若是線程沒有被阻塞,這時調用interrupt()將不起做用,直到執行到wait(),sleep(),join()時,才立刻會拋出 InterruptedException。

線程A在執行sleep,wait,join時,線程B調用線程A的interrupt方法,的確這一個時候A會有InterruptedException 異常拋出來。但這實際上是在sleep,wait,join這些方法內部會不斷檢查中斷狀態的值,而本身拋出的InterruptedException。若是線程A正在執行一些指定的操做時如值,for,while,if,調用方法等,不會去檢查中斷狀態,則線程A不會拋出 InterruptedException,而會一直執行着本身的操做。

注意:

當線程A執行到wait(),sleep(),join()時,拋出InterruptedException後,中斷狀態已經被系統復位了,線程A調用Thread.interrupted()返回的是false。

若是線程被調用了interrupt(),此時該線程並不在wait(),sleep(),join()時,下次執行wait(),sleep(),join()時,同樣會拋出InterruptedException,固然拋出後該線程的中斷狀態也會被系統復位。

1. sleep() &interrupt()

線程A正在使用sleep()暫停着: Thread.sleep(100000),若是要取消它的等待狀態,能夠在正在執行的線程裏(好比這裏是B)調用a.interrupt()[a是線程A對應到的Thread實例],令線程A放棄睡眠操做。即,在線程B中執行a.interrupt(),處於阻塞中的線程a將放棄睡眠操做。

當在sleep中時線程被調用interrupt()時,就立刻會放棄暫停的狀態並拋出InterruptedException。拋出異常的,是A線程。

2. wait() &interrupt()

線程A調用了wait()進入了等待狀態,也能夠用interrupt()取消。不過這時候要注意鎖定的問題。線程在進入等待區,會把鎖定解除,當對等待中的線程調用interrupt()時,會先從新獲取鎖定,再拋出異常。在獲取鎖定以前,是沒法拋出異常的。

3. join() &interrupt()

當線程以join()等待其餘線程結束時,當它被調用interrupt(),它與sleep()時同樣,會立刻跳到catch塊裏.。

注意,調用的interrupt()方法,必定是調用被阻塞線程的interrupt方法。如在線程a中調用線程t.interrupt()。

相關文章
相關標籤/搜索