java多线程生产消费打印输出倒顺序情况的原因

问题如下,一段简单的代码:

public class testPC2 {
    public static void main(String[] args) {
        TV tv=new TV();
        new Publish(tv).start();
        new Audience(tv).start();
    }
}

class TV {
    String name;
    boolean flag = true;

    public synchronized void play(String name) {
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.name=name;
        this.flag=!this.flag;
        this.notifyAll();

    }

    public synchronized String watch() {
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.flag=!this.flag;
        this.notifyAll();
        return this.name;
    }
}

class Publish extends Thread {
    TV tv;

    public Publish(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        String str;
        for (int i = 0; i < 20; i++) {
            if (i % 2 == 0) {
                str = "快乐大本营";
            } else {
                str = "抖音:记录美好生活";
            }
            tv.play(str+(i+1));
            System.out.println("生产了"+tv.name);
        }
    }
}

class Audience extends Thread {
    TV tv;

    public Audience(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("消费了-->"+tv.watch());
        }
    }
}

如下打印偶尔出现生产和消费倒序输出,消费方会抢线程?不知其中原因,望大佬告知。

生产了快乐大本营1
消费了-->快乐大本营1
消费了-->抖音:记录美好生活2
生产了抖音:记录美好生活2
生产了快乐大本营3
消费了-->快乐大本营3
消费了-->抖音:记录美好生活4
生产了抖音:记录美好生活4
生产了快乐大本营5
消费了-->快乐大本营5
生产了抖音:记录美好生活6
消费了-->抖音:记录美好生活6
消费了-->快乐大本营7
生产了快乐大本营7
生产了抖音:记录美好生活8
消费了-->抖音:记录美好生活8
生产了快乐大本营9
消费了-->快乐大本营9
生产了抖音:记录美好生活10
消费了-->抖音:记录美好生活10
生产了快乐大本营11
消费了-->快乐大本营11
生产了抖音:记录美好生活12
消费了-->抖音:记录美好生活12
生产了快乐大本营13
消费了-->快乐大本营13
消费了-->抖音:记录美好生活14
生产了抖音:记录美好生活14
生产了快乐大本营15
消费了-->快乐大本营15
生产了抖音:记录美好生活16
消费了-->抖音:记录美好生活16
生产了快乐大本营17
消费了-->快乐大本营17
消费了-->抖音:记录美好生活18
生产了抖音:记录美好生活18
生产了快乐大本营19
消费了-->快乐大本营19
生产了抖音:记录美好生活20
消费了-->抖音:记录美好生活20

问题找到,不是锁不锁公共资源的问题,实际上如果公共资源有缓存比如条件生产超过10个才wait(),那就得等它每生产完10个才能消费,显然不符合应用场景。实际上边生产边消费,才符合多线程的意义。
所以原代码没错,是System.out.println()这个方法没在方法锁里。应该把它放在notify之前。

阅读 1.5k
1 个回答

在生产者与消费者 run里面加上synchronized,就可以得到你想要的结果,共享资源的读写访问需要同步

  synchronized(tv){
                    tv.play(str + (i + 1));
                    System.out.println( "生产了" + tv.name );
   }

 synchronized(tv){
                    System.out.println( "消费了-->" + tv.watch());
                }

image.png

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