鍍金池/ 問答/HTML5  Linux/ 兩個線程中有一個沒有經(jīng)過while()條件判斷,就直接進(jìn)入while循環(huán)體了,導(dǎo)

兩個線程中有一個沒有經(jīng)過while()條件判斷,就直接進(jìn)入while循環(huán)體了,導(dǎo)致多輸出一次數(shù)據(jù)?

主要實現(xiàn)功能是:使用兩個線程循環(huán)打印AB。

出現(xiàn)的問題:當(dāng)調(diào)用PrintB中的run()時,通過Debug模式調(diào)試發(fā)現(xiàn),是先進(jìn)入循環(huán)體,再進(jìn)行的條件判斷,導(dǎo)致最后的結(jié)果就會多輸出一次數(shù)據(jù)。

源碼如下:

    線程共享資源:Printer
    /**
 * 共享資源:打印機
 * @author Tangxkun
 *
 */
public class Printer {
    
    //最大打印次數(shù)
    private final int MAX_COUNT = 5;
    //false表示該打印機未打印A,true表示該打印機正在打印A
    private boolean printingA = false;
    private int count = 0;
    
    public synchronized void printA(){
        System.out.println(count++);
        printingA = true;
        System.out.println("A");
        notifyAll();
    }
    public synchronized void printB(){
        System.out.println(count++);
        printingA = false;
        System.out.println("B");
        notifyAll();
    }
    public synchronized void aWaiting() throws InterruptedException{
        while(printingA == true){
            wait();
        }
    }
    public synchronized void bWaiting() throws InterruptedException{
        while(printingA == false){
            wait();
        }
    }
    
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public int getMAX_COUNT() {
        return MAX_COUNT;
    }
}

打印A的線程任務(wù):

/**
 * 打印A的線程
 * @author Tangxkun
 *
 */
public class PrintA implements Runnable{

    private Printer printer;
    
    public PrintA(Printer printer) {
        super();
        this.printer = printer;
    }

    @Override
    public void run() {
        while(printer.getCount() < printer.getMAX_COUNT()){

            printer.printA();
            
            try {
                printer.aWaiting();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }
}

打印B的線程任務(wù):

/**
 * 打印B的線程
 * @author Tangxkun
 *
 */
public class PrintB implements Runnable{

    private Printer printer;
    
    public PrintB(Printer printer) {
        super();
        this.printer = printer;
    }

    @Override
    public void run() {
        while(printer.getCount() < printer.getMAX_COUNT()){

            try {
                printer.bWaiting();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            printer.printB();
            
        }
    }

}

測試代碼:

/**
 * 測試代碼
 * @author Tangxkun
 *
 */
public class Test {

    public static void main(String[] args) {
        
        Printer printer = new Printer();
        PrintA printA = new PrintA(printer);
        PrintB printB = new PrintB(printer);
        
        Thread threadA = new Thread(printA,"A");
        Thread threadB = new Thread(printB, "B");
        
        threadA.start();
        threadB.start();
        
    }
}

當(dāng)設(shè)置MAX_COUNT=5時,輸出結(jié)果為:
clipboard.png

當(dāng)設(shè)置MAX_COUNT=6時,輸出結(jié)果為:
clipboard.png

當(dāng)設(shè)置MAX_COUNT=7時,輸出結(jié)果為:
clipboard.png

燒腦了半天還是沒有找出端倪,所以來請教一下各位大神!

回答
編輯回答
鐧簞噯

原因終于找到了,是自己沒有理解清楚線程掛起的概念。第一次執(zhí)行線程B的時候,會while條件判斷進(jìn)入,然后掛起,并沒有執(zhí)行printer.printB(),當(dāng)線程A喚醒線程B時,線程B從掛起時刻的代碼處繼續(xù)往后執(zhí)行(執(zhí)行printer.printB(),完成之前被掛起的任務(wù)),而不是重新開始執(zhí)行run(),也就是說,不會再進(jìn)行while條件判斷,最后再次進(jìn)入while循環(huán)。

2018年8月15日 03:16