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(); } } }
生产者消费者模式的Java实现
最新推荐文章于 2023-06-15 17:24:22 发布