Java 線程間通信

線程間的交互和通信

  1. 一個(gè)線程啟動另一個(gè)線程

    public static void main(String[] args){
      new Thread().start();
    }
    

    主線程啟動另一個(gè)線程。

  2. 一個(gè)線程終結(jié)另個(gè)一線程
    A. Thread.stop()來停止一個(gè)線程,但是已經(jīng)被棄用了,因?yàn)?code>stop結(jié)果是不可預(yù)期的雹姊,它是直接將線程干掉了赁还,即是你的業(yè)務(wù)剛執(zhí)行到一半棚饵,這樣就導(dǎo)致結(jié)果是不可預(yù)期的辆苔,比較危險(xiǎn)楼镐。

      Thread thread = new Thread();
      thread.start();
      thread.stop();
    

    B. Thread.interrupt()來中斷一個(gè)線程的執(zhí)行喷橙。它的原理是調(diào)用interrupt方法后啥么,將該線程編輯為中斷狀態(tài),需要我們自己處理這個(gè)狀態(tài)贰逾。

      Thread thread = new Thread(){
          @Override
          public void run(){
              if(isInterrupted()){
                  //do something
              }
          }
      };
      thread.start();
      thread.interrupt();
    

    判斷一個(gè)線程是否標(biāo)記為中斷狀態(tài)悬荣,可以使用thread.isInterrupted(),也可以使用Thead的靜態(tài)方法Thread.interruped()疙剑,二者的區(qū)別是前者可以重復(fù)多次使用氯迂,后者只能使用一次践叠,因?yàn)槭褂弥髸?biāo)記復(fù)位,即置為false嚼蚀,實(shí)際使用根據(jù)自己具體的邏輯來具體使用哪種方式禁灼。

    C. 當(dāng)一個(gè)線程正在休眠中,此時(shí)被中斷轿曙,會怎樣弄捕?
    答案是會立即拋出InterruptedException,然后線程會被立即結(jié)束导帝,但是中斷標(biāo)志一直是false守谓。因?yàn)楫?dāng)處于休眠狀態(tài),說明這個(gè)線程目前沒有在處理事情您单,也就是說可以立即打斷斋荞,也不會產(chǎn)生影響,所以會被立即終止虐秦。這也是當(dāng)我們寫Thread.sleep(10); 的時(shí)候要求強(qiáng)制捕獲InterruptedException的原因平酿,所以如果我們有需要?jiǎng)t要在異常中處理中斷的后續(xù)邏輯。

  3. 兩個(gè)線程互相配合
    需要使用wait()notify()以及notifyAll()羡疗,這里有必要說明下,這3個(gè)方法是針對monitor來說的别洪,并不是針對線程叨恨,需要等的是monitor,需要喚醒的也是monitor挖垛,和線程無關(guān)痒钝,而且這3個(gè)方法也必須是在同步代碼塊中才可以使用。
    下面我們來簡單說一下waitnotify的工作模型痢毒。

    工作模型

首先我們看下這段代碼送矩,有兩個(gè)同步方法methodAmethodB,他們的鎖對象都是this哪替,即monitor是同一個(gè)栋荸,下面來說明下這個(gè)工作模型。

當(dāng)ThreadA先訪問methodB時(shí)凭舶,它先來到等待訪問排隊(duì)區(qū)晌块,發(fā)現(xiàn)里面沒人,就他自己帅霜,于是它從monitor那里拿到了鎖匆背,此時(shí)的線程正在訪問區(qū)里面放的是ThreadA。但是methodB里面的代碼是wait()身冀,此時(shí)monitor會將ThreadA放到右面的等待喚醒區(qū)钝尸,同時(shí)ThreadA所持有的鎖也會被釋放括享,正在訪問區(qū)是空的。這時(shí)ThreadB來了珍促,想訪問methodA铃辖,它問了下monitor,我可以訪問methodA嗎踢星,因?yàn)榇藭r(shí)的ThreadA的鎖已經(jīng)釋放了澳叉,它理所當(dāng)然的可以訪問methodA,此時(shí)的線程正在訪問區(qū)中里面放的是ThreadB, ThreadB拿著鎖來到了methodA內(nèi)部沐悦,此時(shí)它發(fā)現(xiàn)里面是notifyAll成洗,所以此時(shí)的monitor就將等待喚醒區(qū)里面的所有等待喚醒的線程都喚醒了,然后ThreadB就是放了鎖藏否,然后罵罵咧咧的走了瓶殃,此時(shí)線程正在訪問區(qū)是空的。等待喚醒區(qū)中的ThreadA被喚醒副签,他只能再次來到等待訪問排隊(duì)區(qū)遥椿,不能插隊(duì)到正在訪問區(qū)中,只能公平的再次去競爭鎖淆储,然后發(fā)下排隊(duì)的就他自己冠场,于是它又從monitor那里拿到了鎖,然后就去訪問methodB了本砰,但是里面又是wait()碴裙,于是乎它又釋放鎖,然后又進(jìn)入了等待喚醒區(qū)点额,可以沒有人再去訪問methodA來告訴monitor區(qū)喚醒喚醒等待區(qū)里面的線程了舔株,此時(shí)ThreadA將永遠(yuǎn)在等待喚醒區(qū)等一輩子。

大致的一個(gè)工作模型就是這樣的还棱,可能描述的不太清楚载慈,但是大致原理是清晰的,相信多看幾遍總會明白的珍手,哈哈哈办铡。。琳要。

這里為什么調(diào)用的是nitofyAll呢料扰,而不是notify呢?因?yàn)獒槍@個(gè)monitor而言焙蹭,有可能等待喚醒區(qū)有好多個(gè)線程正在等待晒杈,而不是一個(gè),如果只喚醒一個(gè)孔厉,那剩下的咋辦拯钻?所以只能一次性喚醒所有的帖努,除非你明確知道等待喚醒區(qū)中只有一個(gè)線程在等待被喚醒。
所以從這個(gè)工作模型來看粪般,wait拼余,notify 以及notifyAll 都是針對monitor而言的,是monitor讓一個(gè)線程區(qū)等待喚醒區(qū)亩歹,也是monitor來進(jìn)行喚醒等待喚醒區(qū)里面的線程匙监,而且waitnotify一定是成對出現(xiàn)的。
下面舉一個(gè)簡單的栗子小作。

 public class Demo {

 public static void main(String[] args) {
     new WaitNotifyTest().runTest();
 }

 private static class WaitNotifyTest{

     private int x;

     void runTest() {
         Thread threadA = new Thread(){
             @Override
             public void run() {
                 try {
                     Thread.sleep(2000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 plus();
             }
         };
         threadA.start();
         Thread threadB = new Thread(){
             @Override
             public void run() {
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 printX();
             }
         };
         threadB.start();
     }

     private synchronized void plus() {
         x++;
         notifyAll();
     }

     private synchronized void printX() {
         if (x == 0) {
             try {
                 wait();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
         System.out.println("The x is: " + x);
     }

 }
}

執(zhí)行結(jié)果如下:


結(jié)果
  1. 插隊(duì)
    將一個(gè)線程插到當(dāng)前線程之前執(zhí)行亭姥,插隊(duì)的方法就是join
    簡單代碼如下:
    public static void main(String[] args) {
        Thread threadA = new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("run method in ThreadA class is finished顾稀。");
            }
        };
        threadA.start();
        try {
            threadA.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main method is finished达罗。");
    }
    

    上述代碼執(zhí)行的結(jié)果:


    執(zhí)行結(jié)果

當(dāng)ThreadA執(zhí)行了join插隊(duì)方法后,main方法所在的線程會等ThradA線程執(zhí)行結(jié)果后在執(zhí)行静秆。
join可以說是簡化后的wait,notify粮揉,只是不需要我們調(diào)用notify

它的作用時(shí)將并行的兩個(gè)線程變成串行化抚笔。

  1. yield扶认。暫時(shí)讓出時(shí)間片,讓給同優(yōu)先級的線程殊橙,這個(gè)時(shí)間很短很短辐宾,讓出之后馬上會再次獲取到時(shí)間片。

由于個(gè)人能力有限蛀柴,如有錯(cuò)誤之處螃概,還望指出矫夯,我會第一時(shí)間驗(yàn)證并修改鸽疾。
理解事物,看本質(zhì)训貌。共勉制肮。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市递沪,隨后出現(xiàn)的幾起案子豺鼻,更是在濱河造成了極大的恐慌,老刑警劉巖款慨,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儒飒,死亡現(xiàn)場離奇詭異,居然都是意外死亡檩奠,警方通過查閱死者的電腦和手機(jī)桩了,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門附帽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人井誉,你說我怎么就攤上這事蕉扮。” “怎么了颗圣?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵喳钟,是天一觀的道長。 經(jīng)常有香客問我在岂,道長奔则,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任洁段,我火速辦了婚禮应狱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祠丝。我一直安慰自己疾呻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布写半。 她就那樣靜靜地躺著岸蜗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叠蝇。 梳的紋絲不亂的頭發(fā)上璃岳,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機(jī)與錄音悔捶,去河邊找鬼铃慷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蜕该,可吹牛的內(nèi)容都是我干的犁柜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼堂淡,長吁一口氣:“原來是場噩夢啊……” “哼馋缅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绢淀,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤萤悴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后皆的,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體覆履,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了硝全。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怪嫌。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖柳沙,靈堂內(nèi)的尸體忽然破棺而出岩灭,到底是詐尸還是另有隱情,我是刑警寧澤赂鲤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布噪径,位于F島的核電站,受9級特大地震影響数初,放射性物質(zhì)發(fā)生泄漏找爱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一泡孩、第九天 我趴在偏房一處隱蔽的房頂上張望车摄。 院中可真熱鬧,春花似錦仑鸥、人聲如沸吮播。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽意狠。三九已至,卻和暖如春疮胖,著一層夾襖步出監(jiān)牢的瞬間环戈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工澎灸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留院塞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓性昭,卻偏偏與公主長得像拦止,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子巩梢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

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

  • 摘自《Java并發(fā)編程的藝術(shù)》 1 volatile和synchronized關(guān)鍵字 關(guān)鍵字volatile可以用...
    沉淪2014閱讀 536評論 0 2
  • 現(xiàn)在計(jì)算機(jī)和智能手機(jī)都是多核處理器括蝠,為了更好地發(fā)揮設(shè)備的性能,提高應(yīng)用程序的體驗(yàn)性饭聚,多線程是必不可少的技術(shù)忌警。線程之...
    落英墜露閱讀 2,458評論 0 4
  • 線程間的通信 線程間通信:多個(gè)線程在處理同一資源,但是任務(wù)卻不同 1 多線程執(zhí)行同一資源: 2 多線程執(zhí)行同一資源...
    柳子陌閱讀 250評論 0 1
  • 一,介紹 本總結(jié)我對于JAVA多線程中線程之間的通信方式的理解法绵,主要以代碼結(jié)合文字的方式來討論線程間的通信箕速,故摘抄...
    那些年的代碼閱讀 163評論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭朋譬,有人歡樂有人憂愁盐茎,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,528評論 28 53