鍍金池/ 問答/Java/ 一個線程打印A,一個線程打印B,一個線程打印C,實現(xiàn)循環(huán)打印ABC 10次。主函

一個線程打印A,一個線程打印B,一個線程打印C,實現(xiàn)循環(huán)打印ABC 10次。主函數(shù)有個小地方不懂!

/*功能:三個線程,一個打印A,一個打印B,一個打印C,主函數(shù)實現(xiàn)循環(huán)打印ABCABCABCABC...  共打印10次ABC*/

public class ThreadABC {
    public static void main(String[] args) {
        Print p = new Print();
        
        /*打印A的進(jìn)程*/
        new Thread(new Runnable() {
            public void run() {
                for(int i = 0;i <10;++i){//我設(shè)置的i打印10次啊
                    p.print_A();
        /*為什么只打印 5 次???!?。?/
        /*加上下面這行代碼,就能正常打印10次,why???*/
                    //try{Thread.sleep();}catch(Exception e){;}
                }
                
            }
        }).start();
        
        /*啟動打印B的線程*/
        new Thread(new Runnable() {
            public void run() {
                while(true)
                p.print_B();
            }
        }).start();
        
        /*啟動打印C的線程*/
        new Thread(new Runnable() {
            public void run() {
                while(true)
                p.print_C();
            }
        }).start();
    }
}

/**/
class Print {
    /*flag用來同步*/
    private int flag = 1;
    /*打印 A */
    synchronized void print_A() {
        
        if(flag == 1) {
            System.out.print("A");
            flag = 2;
            try {this.notifyAll();}catch(Exception e) {e.printStackTrace();}
        }
        else {
            try {this.wait();}catch(Exception e) {e.printStackTrace();}
        }
    }
    /*打印B*/
    synchronized void print_B() {
        if(flag == 2) {
            System.out.print("B");
            flag = 3;
            try {this.notifyAll();}catch(Exception e) {e.printStackTrace();}
        }
        else {
            try {this.wait();}catch(Exception e) {e.printStackTrace();}
        }
    }
    /*打印C*/
        synchronized void print_C() {
        if(flag == 3) {
            System.out.println("C");
            flag = 1;
            try {this.notifyAll();}catch(Exception e) {e.printStackTrace();}
        }
        else {
            try {this.wait();}catch(Exception e) {e.printStackTrace();}
        }
    }
}
回答
編輯回答
寫榮

1:首先指出代碼的小問題——p變量應(yīng)該是final類型,否則實現(xiàn)了Runnable接口的匿名內(nèi)部類是訪問不到的;

2:這個代碼實現(xiàn)有點問題,打印A的線程一直循環(huán),但是實際打印A的線程是依賴flag的值,并且flag的值在打印B/C的線程都有修改,問題就出在這,試想執(zhí)行了一次print_A后,如若沒有你添加的sleep等待,循環(huán)回來繼續(xù)執(zhí)行print_A,但是此時flag已經(jīng)被打印B的線程改成了3,但是打印C的線程還沒執(zhí)行完,flag還是3,然后notify喚醒print_A,但是flag不是1,繼續(xù)wait,浪費了一次循環(huán)。

不知道說清楚沒
所以你加了sleep后print_A執(zhí)行的時候flag肯定已經(jīng)置為1了?。〔患硬淮_定

你可以在打印A的循環(huán)體里面添加System.out.println();感受下,的確循環(huán)了10次

2017年6月27日 05:04
編輯回答
維他命

我把你的代碼修改了,你抄一遍體會一下:
圖片描述

圖片描述

2017年7月11日 15:43