Java三個線程分別打印十次A,B,C,要求打印出ABCABC....的形式

今天一位同學問我題目中的這個問題,并給了我下面的代碼,花了好久才看懂,這里總結一下.

實現(xiàn)代碼如下所示:

package com.multithread.wait;  
public class MyThreadPrinter2 implements Runnable {     
        
    private String name;     
    private Object prev;     
    private Object self;     
    
    private MyThreadPrinter2(String name, Object prev, Object self) {     
        this.name = name;     
        this.prev = prev;     
        this.self = self;     
    }     
    
    @Override    
    public void run() {     
        int count = 10;     
        while (count > 0) {     
            synchronized (prev) {     
                synchronized (self) {     
                    System.out.print(name);     
                    count--;    
                      
                    self.notify();     
                }     
                try {     
                    prev.wait();     
                } catch (InterruptedException e) {     
                    e.printStackTrace();     
                }     
            }     
    
        }     
    }     
    
    public static void main(String[] args) throws Exception {     
        Object a = new Object();     
        Object b = new Object();     
        Object c = new Object();     
        MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);     
        MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);     
        MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);     
             
             
        new Thread(pa).start();  
        Thread.sleep(100);  //確保按順序A、B、C執(zhí)行  
        new Thread(pb).start();  
        Thread.sleep(100);    
        new Thread(pc).start();     
        Thread.sleep(100);    
        }     
}

首先,我們提出一個概念模型,就是Java對象中,包含了這么兩部分內容:

ArrayList<Thread> threadsWhoWaitForThisObject
Thread threadWhoEnterTheMonitor

在執(zhí)行synchronized塊時,線程會比較相應對象的threadWhoEnterTheMonitor是否是null或者當前線程,如果是的話,就將相應對象的threadWhoEnterTheMonitor設置為當前線程,并且執(zhí)行synchronized塊.當線程調用wait()方法時,會將線程加入到對應對象的threadsWhoWaitForThisObject,并且將對應對象的threadWhoEnterTheMonitor設置為null,讓其他的線程可以得到執(zhí)行.當線程從synchronized塊中出來時,也會將對應對象的threadsWhoEnterTheMonitor設置為null.

當然,這只是一個概念模型.Java中對象是否包含上面提到的這兩個區(qū)域,我還不清楚.

清楚了上面的概念模型后,我們照著上面的代碼走一個循環(huán)就清楚了.

首先,是線程pa執(zhí)行,其次是pb,最后是線程pc執(zhí)行.同時有三個對象,a,b,c,它們和上面的三個線程是一一對應的關系.下面我們將會從這三個執(zhí)行期間a,b,c中的threadWhoEnterTheMonitor以及threadsWhoWaitForThisObject的變化來解釋其實現(xiàn)原理.

在第一次pa執(zhí)行期間,三個對象的threadWhoEnterTheMonitor以及threadsWhoWaitForThisObject的變化如下:

c's threadWhoEnterTheMonitor: pa -> null
a's threadWhoEnterTheMonitor: pa -> null
b's threadWhoEnterTheMonitor: null

a's threadsWhoWaitForThisObject: null
b's threadsWhoWaitForThisObject: null
c's threadsWhoWaitForThisObject: pa

在第一次pb執(zhí)行期間,三個對象的threadWhoEnterTheMonitor以及threadsWhoWaitForThisObject的變化如下:

a's threadWhoEnterTheMonitor: pb -> null
b's threadWhoEnterTheMonitor: pb -> null
c's threadWhoEnterTheMonitor: null

a's threadsWhoWaitForThisObject: pb
b's threadsWhoWaitForThisObject: null
c's threadsWhoWaitForThisObject: pa

在第一次pc執(zhí)行期間,三個對象的threadWhoEnterTheMonitor以及threadsWhoWaitForThisObject的變化如下:

a's threadWhoEnterTheMonitor: null
b's threadWhoEnterTheMonitor: pc -> null
c's threadWhoEnterTheMonitor: pc -> null

a's threadsWhoWaitForThisObject: pb
b's threadsWhoWaitForThisObject: pc
c's threadsWhoWaitForThisObject: pa -> null

在第一次執(zhí)行pa和pb的期間,由于prev對象對應的threadsWhoWaitForThisObject是null,所以實際上self.notify()是不會起作用的.

而在第一次執(zhí)行pc的期間,c's threadsWhoWaitForThisObject開始是pa,所以是會喚醒pa的.等到pc的synchronized執(zhí)行完后,此時盡管三個對象的threadWhoEnterTheMonitor都是null,但是此時pb和pc都沒有被喚醒,所以不存在競爭的問題.

后面的迭代就跟第一次基本上差不多了,各位可以自行嘗試走一遍.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,115評論 1 18
  • 本文主要講了java中多線程的使用方法、線程同步、線程數據傳遞、線程狀態(tài)及相應的一些線程函數用法、概述等。 首先講...
    李欣陽閱讀 2,602評論 1 15
  • 該文章轉自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍閱讀 7,472評論 3 87
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,806評論 18 399
  • 文/阿蓮 晚上8:30。我一邊碼字一邊通知兒子:“今晚我還要寫作,你先睡?!?8:50,兒子:“媽媽你快點做完事好...
    阿蓮簡師閱讀 675評論 2 9

友情鏈接更多精彩內容