两个线程中有一个没有经过while()条件判断,就直接进入while循环体了,导致多输出一次数据?

主要实现功能是:使用两个线程循环打印AB。

出现的问题:当调用PrintB中的run()时,通过Debug模式调试发现,是先进入循环体,再进行的条件判断,导致最后的结果就会多输出一次数据。

源码如下:

    线程共享资源:Printer
    /**
 * 共享资源:打印机
 * @author Tangxkun
 *
 */
public class Printer {
    
    //最大打印次数
    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的线程任务:

/**
 * 打印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的线程任务:

/**
 * 打印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();
        
    }
}

当设置MAX_COUNT=5时,输出结果为:
clipboard.png

当设置MAX_COUNT=6时,输出结果为:
clipboard.png

当设置MAX_COUNT=7时,输出结果为:
clipboard.png

烧脑了半天还是没有找出端倪,所以来请教一下各位大神!

阅读 2.3k
1 个回答

原因终于找到了,是自己没有理解清楚线程挂起的概念。第一次执行线程B的时候,会while条件判断进入,然后挂起,并没有执行printer.printB(),当线程A唤醒线程B时,线程B从挂起时刻的代码处继续往后执行(执行printer.printB(),完成之前被挂起的任务),而不是重新开始执行run(),也就是说,不会再进行while条件判断,最后再次进入while循环。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进