Java基礎之線程

一隆圆、線程分類

二、線程的實現(xiàn)方式

三翔烁、線程的狀態(tài)

四、線程的核心方法

  1. sleep()方法:該方法屬于Thread類旨涝,是線程用來控制自身流程的蹬屹,在線程休眠的過程中不會釋放所持有的對象鎖。
    在指定的毫秒數(shù)加指定的納秒數(shù)內(nèi)讓當前正在執(zhí)行的線程休眠(暫停執(zhí)行)白华,此操作受到系統(tǒng)計時器和調(diào)度程序精度和準確性的影響慨默。該線程不丟失任何監(jiān)視器的所屬權

  2. wait()方法:該方法屬于Object類且為final方法弧腥,無法被子類覆寫厦取,用來線程間的通信,線程會放棄對象鎖管搪,進入等待此對象的等待鎖定池虾攻,只有針對此對象調(diào)用notify()方法后本線程才進入對象鎖定池準備獲取對象鎖進入運行狀態(tài)铡买。此方法一般與notify()或notifyAll()方法配套使用。

  3. notify()方法:該方法屬于Object類且為final方法霎箍,無法被子類覆寫奇钞,用來線程間通信。通常由當前對象調(diào)用該方法形如Object.notify()喚醒一個正在等待該對象的monitor(鎖)的線程漂坏,當有多個線程都在等待該對象的monitor(鎖)的話景埃,則只能喚醒其中一個線程,具體喚醒哪個線程則不得而知顶别。調(diào)用notify()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)谷徙。

  4. notifyAll()方法:該方法屬于Object類且為final方法,無法被子類覆寫驯绎,用來線程間通信完慧。notifyAll()方法能夠喚醒所有正在等待該對象的monitor(鎖)的線程,這一點與notify()方法是不同的条篷。notify()和notifyAll()方法只是喚醒等待該對象的monitor(鎖)的線程骗随,并不決定哪個線程能夠獲取到monitor(鎖)。你可以用 notify 和 notifyAll 來通知那些在此監(jiān)視器上等待的線程重新開始運行赴叹。不同之處在于鸿染,notify 僅僅通知一個線程,并且我們不知道哪個線程會收到通知乞巧,然而 notifyAll 會通知所有等待中的線程涨椒。換言之,如果只有一個線程在等待一個信號燈绽媒,notify和notifyAll都會通知到這個線程蚕冬。但如果多個線程在等待這個信 號燈,那么notify只會通知到其中一個是辕,而其它線程并不會收到任何通知囤热,而notifyAll會喚醒所有等待中的線程。wait()會使持有該對象鎖的線程釋放占有的鎖,notify和notifyAll不會使持有該對象鎖的線程釋放占用的鎖获三。

  5. join()方法:join是Thread類的一個方法旁蔼,啟動線程后直接調(diào)用,例如:

Thread t = new AThread(); t.start(); t.join();

在很多情況下疙教,主線程生成并起動了子線程棺聊,如果子線程里要進行大量的耗時的運算,主線程往往將于子線程之前結束贞谓,但是如果主線程處理完其他的事務后限佩,需要用到子線程的處理結果,也就是主線程需要等待子線程執(zhí)行完成之后再結束,這個時候就要用到join()方法了祟同。
即join()的作用是:“等待該線程終止”作喘,這里需要理解的就是該線程是指的主線程等待子線程的終止。也就是在子線程調(diào)用了join()方法后面的代碼耐亏,只有等到子線程結束了才能執(zhí)行徊都。

  1. interrupt()方法:
    interrupt()并不直接中斷線程,而是設定一個中斷標識广辰,然后由程序進行中斷檢查暇矫,確定是否中斷。
  • sleep() &interrupt()
    線程A正在使用sleep()暫停著:Thread.sleep(100000);
    如果要取消他的等待狀態(tài),可以在正在執(zhí)行的線程里(比如這里是B)調(diào)用a.interrupt();
    令線程A放棄睡眠操作,這里a是線程A對應到的Thread實例執(zhí)行interrupt()時,并不需要獲取Thread實例的鎖定.任何線程在任何時刻,都可以調(diào)用其他線程interrupt().當sleep中的線程被調(diào)用interrupt()時,就會放棄暫停的狀態(tài).并拋出InterruptedException.丟出異常的,是A線程.
  • wait() & interrupt()
    線程A調(diào)用了wait()進入了等待狀態(tài),也可以用interrupt()取消.
    不過這時候要小心鎖定的問題.線程在進入等待區(qū),會把鎖定解除,當對等待中的線程調(diào)用interrupt()時(注意是等待的線程調(diào)用其自己的interrupt()),會先重新獲取鎖定,再拋出異常.在獲取鎖定之前,是無法拋出異常的.
  • join() & interrupt()
    當線程以join()等待其他線程結束時,一樣可以使用interrupt()取消之.因為調(diào)用join()不需要獲取鎖定,
    故與sleep()時一樣,會馬上跳到catch塊里.注意是隨調(diào)用interrupt()方法,一定是阻塞的線程來調(diào)用其自己的interrupt方法.如在線程a中調(diào)用來線程t.join().則a會等t執(zhí)行完后在執(zhí)行t.join后的代碼,當在線程b中調(diào)用來a.interrupt()方法,則會拋出InterruptedException择吊。
  • interrupt()只是改變中斷狀態(tài)而已
    interrupt()不會中斷一個正在運行的線程李根。這一方法實際上完成的是,在線程受到阻塞時拋出一個中斷信號几睛,這樣線程就得以退出阻塞的狀態(tài)房轿。更確切的說,如果線程被Object.wait,Thread.join和Thread.sleep三種方法之一阻塞所森,那么囱持,它將接收到一個中斷異常(InterruptedException),從而提早地終結被阻塞狀態(tài)焕济。
      如果線程沒有被阻塞纷妆,這時調(diào)用interrupt()將不起作用;否則,線程就將得到異常(該線程必須事先預備好處理此狀況)晴弃,接著逃離阻塞狀態(tài)掩幢。
      線程A在執(zhí)行sleep,wait,join時,線程B調(diào)用A的interrupt方法,的確這一個時候A會有InterruptedException異常拋出來.但這其實是在sleep,wait,join這些方法內(nèi)部會不斷檢查中斷狀態(tài)的值,而自己拋出的InterruptedException。
      如果線程A正在執(zhí)行一些指定的操作時如賦值,for,while,if,調(diào)用方法等,都不會去檢查中斷狀態(tài),所以線程A不會拋出InterruptedException,而會一直執(zhí)行著自己的操作.當線程A終于執(zhí)行到wait(),sleep(),join()時,才馬上會拋出InterruptedException.
      若沒有調(diào)用sleep(),wait(),join()這些方法,或是沒有在線程里自己檢查中斷狀態(tài)自己拋出InterruptedException的話,那InterruptedException是不會被拋出來的.

五上鞠、wait()方法和sleep()方法的區(qū)別

相同點:

  • 通過Thread.sleep()和Object.wait()方法都可以暫停當前的線程际邻,對于CPU資源來說,不管是哪種方式暫停的線程芍阎,都表示它暫時不再需要CPU的執(zhí)行時間世曾。OS會將執(zhí)行時間分配給其它線程。

不同點:

  • sleep()是Thread類中定義的方法,wait()是Object類中定義的方法;
  • 調(diào)用Thread.sleep()方法的線程不會釋放該線程所擁有的鎖谴咸,當前對象調(diào)用Object.wait()方法后持有該對象鎖的線程會釋放所持有的對象鎖度硝。
  • 當前對象調(diào)用Object.wait()方法后需要別的線程執(zhí)行notify()/notifyAll()才能夠有機會重新獲得CPU執(zhí)行時間。

六寿冕、wait(),notify(),notifyAll()

  1. 你可以使用wait和notify函數(shù)來實現(xiàn)線程間通信。你可以用它們來實現(xiàn)多線程(>3)之間的通信椒袍。
  2. 永遠在synchronized的函數(shù)或?qū)ο罄锸褂脀ait驼唱、notify和notifyAll,不然Java虛擬機會生成 IllegalMonitorStateException驹暑。
  3. 永遠在while循環(huán)里而不是if語句下使用wait玫恳。這樣辨赐,循環(huán)會在線程睡眠前后都檢查wait的條件,并在條件實際上并未改變的情況下處理喚醒通知京办。
  4. 永遠在多線程間共享的對象(在生產(chǎn)者消費者模型里即緩沖區(qū)隊列)上使用wait掀序。
  5. 相較于notify()方法,多使用notifyAll()方法惭婿。

六不恭、代碼示例

假設線程A實現(xiàn)了Runnable接口,其run方法如下:

@Override
public void run(){
synchronized(obj) {
  while(!condition) {
    obj.wait();
  }
  obj.doSomething();
}
}

當線程A獲得了obj鎖后,發(fā)現(xiàn)條件condition不滿足财饥,無法繼續(xù)下一處理换吧,于是線程A就wait() , 放棄對象鎖.交由系統(tǒng)進行線程的調(diào)度。
假設線程B也實現(xiàn)了Runnable接口,其run方法如下:

@Override
public void run(){
synchronized(obj) {
  condition = true;
  obj.notify();
}
}

如果B持有了obj對象鎖之后钥星,使得線程A的condition條件滿足了沾瓦,就可以喚醒等待obj對象鎖的線程A:

幾點說明:

  • 調(diào)用obj的wait(), notify()方法前,必須獲得obj鎖谦炒,也就是必須寫在synchronized(obj) {…} 代碼段內(nèi)贯莺。
  • 調(diào)用obj.wait()后,線程A就釋放了obj的鎖宁改,否則線程B無法獲得obj鎖缕探,也就無法在synchronized(obj) {…} 代碼段內(nèi)喚醒等待obj對象鎖的線程A。
  • 當obj.wait()方法返回后透且,線程A需要再次獲得obj鎖撕蔼,才能繼續(xù)執(zhí)行。
  • 如果A1,A2,A3都在obj.wait()秽誊,則B調(diào)用obj.notify()只能喚醒A1,A2,A3中的一個(具體哪一個由JVM決定)鲸沮。
  • obj.notifyAll()則能全部喚醒A1,A2,A3,但是要繼續(xù)執(zhí)行obj.wait()的下一條語句锅论,必須獲得obj鎖讼溺,因此,A1,A2,A3只有一個有機會獲得鎖繼續(xù)執(zhí)行最易,例如A1怒坯,其余的需要等待A1釋放obj鎖之后才能繼續(xù)執(zhí)行。
  • 當B調(diào)用obj.notify/notifyAll的時候藻懒,B正持有obj鎖剔猿,因此,A1,A2,A3雖被喚醒嬉荆,但是仍無法獲得obj鎖归敬。直到B退出synchronized塊,釋放obj鎖后,A1,A2,A3中的一個才有機會獲得鎖繼續(xù)執(zhí)行汪茧。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末椅亚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子舱污,更是在濱河造成了極大的恐慌呀舔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扩灯,死亡現(xiàn)場離奇詭異媚赖,居然都是意外死亡,警方通過查閱死者的電腦和手機驴剔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門省古,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丧失,你說我怎么就攤上這事豺妓。” “怎么了布讹?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵琳拭,是天一觀的道長。 經(jīng)常有香客問我描验,道長白嘁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任膘流,我火速辦了婚禮絮缅,結果婚禮上,老公的妹妹穿的比我還像新娘呼股。我一直安慰自己耕魄,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布彭谁。 她就那樣靜靜地躺著吸奴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缠局。 梳的紋絲不亂的頭發(fā)上则奥,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音狭园,去河邊找鬼读处。 笑死,一個胖子當著我的面吹牛唱矛,可吹牛的內(nèi)容都是我干的档泽。 我是一名探鬼主播俊戳,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼馆匿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起燥滑,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤渐北,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后铭拧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赃蛛,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年搀菩,在試婚紗的時候發(fā)現(xiàn)自己被綠了呕臂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡肪跋,死狀恐怖歧蒋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情州既,我是刑警寧澤谜洽,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站吴叶,受9級特大地震影響阐虚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚌卤,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一实束、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逊彭,春花似錦咸灿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至签赃,卻和暖如春谷异,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锦聊。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工歹嘹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人孔庭。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓尺上,卻偏偏與公主長得像材蛛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怎抛,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 寫在前面的話: 這篇博客是我從這里“轉(zhuǎn)載”的卑吭,為什么轉(zhuǎn)載兩個字加“”呢?因為這絕不是簡單的復制粘貼马绝,我花了五六個小...
    SmartSean閱讀 4,711評論 12 45
  • 該文章轉(zhuǎn)自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍閱讀 7,335評論 3 87
  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,952評論 1 18
  • 本文主要講了java中多線程的使用方法豆赏、線程同步、線程數(shù)據(jù)傳遞富稻、線程狀態(tài)及相應的一些線程函數(shù)用法掷邦、概述等。 首先講...
    李欣陽閱讀 2,442評論 1 15
  • 一椭赋、進程和線程 進程 進程就是一個執(zhí)行中的程序?qū)嵗Ц冢總€進程都有自己獨立的一塊內(nèi)存空間,一個進程中可以有多個線程哪怔。...
    阿敏其人閱讀 2,609評論 0 13