生产者消费者模式的Java实现

1.在《Java编程思想》第4版并发一章的“21.5.3 生产者与消费者”节看到的生产者和消费者定义了两个对象,分别在对象内部使用自身调用wait(就是synchronized(this)内部 调用了 wait() , 后面的notify再synchronized(另外一个对象 比如restaurant.chef) 调用另外一个对象的notifyAll();
这种方法相当于是生产者和消费者都要加锁和通知,有些繁琐?(或者有谁觉得更好?欢迎讨论)

之前面试有遇到生产者消费者的问题。
我:想到的是使用两个同步的对象。
面试官:太复杂了,一个就可以。
我:那应该也可以,但是当时没有具体的用语言实现,所以细节上面没有考虑的太多。

刚上网搜索了一下,发现有使用多种实现方法来实现的(强!)应该是花了一些时间的。

Java生产者消费者的三种实现
https://www.cnblogs.com/xindoo/p/11426659.html

看他的第一种实现,使用了一个队列。把这个队列作为锁对象。于是想到能不能简化一下,使用一个产品对象来做互斥呢?
具体实现:定义了一个String的product对象。
然后使用product做同步。初值赋值的是“”。
生产者:当product != ""时,使用product.wait等待。否则就给product赋值当前时间的字符串。然后调用product.notifyAll()通知。
消费者:当product == ""时,使用product.wait等待。否则就给product赋值"",然后调用product.notifyAll()通知。
初看起来好像是没有问题,但是运行起来就是一直在不停的循环执行下去。
这里犯了几个错误:
1)开始的时候没有加入通知对方的方法,生产者和消费者都只加了wait,使得两个线程启动之后,只执行了一个. 当时只执行了生产者的方法。消费者根本没有执行。
2)加入product.notifyAll()的方法。但是执行还是一次。返回去对比前面文章的实现。
3)对比发现没有在生产者和消费者的run()方法里面加入死循环,导致执行一次就结束了。
4)加入死循环,但是会不停的执行下去,没有按照设定的方式交替运行。

这个可能是什么原因呢?
思考?
对了这里synchronized的对象是String对象,被赋值不同的值的时候,会发生改变!!!从而使得同步失效!!!
于是定义了一个final的Object对象,作为生产者和消费者的公用的一个同步对象,问题解决(记录下来备忘)。
代码如下:

package com.study.arch.studyalgrithom.thread;

public class ProducerConsumer {
    private final Object syncObject = new Object();  //注意这里synchronized使用的同步对象不能是变化的,否则就锁不住了,会出错!!
    private String product = "";  //注意不能使用这个对象来做锁,因为这个对象在变化。但是如果使用队列,因为一开始就new了一个对象,所以不会变化,可以作为同步的对象的。

    class Producer implements Runnable {

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                synchronized (syncObject) {
                    while (product != "") {
                        try {
                            System.out.println("Producer#####product.wait()-------" + product);
                            syncObject.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    product = System.currentTimeMillis() + "------";
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("Producer#####" + product);
                    syncObject.notifyAll();
                }
            }
        }
    }

    class Consumer implements Runnable {

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                synchronized (syncObject) {
                    while (product == "") {
                        System.out.println("Consumer#####product.wait()-------" + product);
                        try {
                            syncObject.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("Consumer######product=" + product);
                    product = "";
                    syncObject.notifyAll();
                }
            }
        }
    }

    public void work() {
        Thread producerThread = new Thread(new Producer());
        Thread consumerThread = new Thread(new Consumer());
        producerThread.start();
        consumerThread.start();
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值