java同步和互斥的应用:生产者消费者之爸爸妈妈儿子女儿苹果橘子编程实现
2012-06-06 17:57
976 查看
转自:http://blog.csdn.net/chunqiuwei/article/details/7622008
下面是程序的具体实现代码,在写这个程序的时候,有点小问题,纠结了很长时间,于是在csdn论坛上发表帖子终于得到了解决
先说说涉及到的类的作用,首先Fruits作为一个水果的父类,Apple和Orange是Fruits类的扩展类。CriticalResources类是临界资源类,作为缓冲区用,里面封装了数组大小为一的Fruits数组,可以看成“盘子”;ProducerOrange为生产橘子的类 ProducerApple为生产桔子的类 ConsumerApple(消费苹果的类) ConsumerOrange(消费桔子的类)
水果类代码如下
苹果类:
桔子类:
下面是作为缓冲区盘子的代码
下面是生产桔子和消费桔子的代码
桔子生产者与消费者代码:
客户端代码
运行结果
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
================================================================================================================================
cr.notifyAll();
我试着把这代去掉,发现运行结果是:
这是为什么呢?
(1) 我们先来看SDK对这个API的解释。
notifyAll用于唤醒在这个对象上等待的线程。一个线程通过调用等待方法来等待对象的监视器。
被唤醒的线程将会以和其它可能完成此对象的同步的线程相同的方式完成.
for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
(2)网上资料:
在java多线程编程中,就要涉及到了对于资源的访问,当多个线程同时访问一个资源的时候就要涉及到一种访问策略。java提供了锁的机制,就是一个线程访问这个资源的时候可以先把这个资源锁住可以用synchronized(the object)来锁定the object,其他访问这个资源的线程就进入阻塞状态,直到当前的线程执行了这个对象的notify或者notifyall其他访问这个对象的阻塞状态的线程才有可能变成就绪状态。其中notify是唤醒一个线程,而notifyall是唤醒所有阻塞进程。
一、转载原文
在《java 同步和互斥程序说明》这篇文章的基础上,来实现下面的程序桌上有一个空盘子,只允许放一个水果。爸爸可以向盘中放苹果,也可以向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时,一次只能放一只水果。
下面是程序的具体实现代码,在写这个程序的时候,有点小问题,纠结了很长时间,于是在csdn论坛上发表帖子终于得到了解决
先说说涉及到的类的作用,首先Fruits作为一个水果的父类,Apple和Orange是Fruits类的扩展类。CriticalResources类是临界资源类,作为缓冲区用,里面封装了数组大小为一的Fruits数组,可以看成“盘子”;ProducerOrange为生产橘子的类 ProducerApple为生产桔子的类 ConsumerApple(消费苹果的类) ConsumerOrange(消费桔子的类)
水果类代码如下
public class Fruits { private String name; public Fruits(String name) { this.name = name; } @Override public String toString() { return name; } public Fruits() { super(); } }
苹果类:
public class Apple extends Fruits { public Apple(String name) { super(name); } public Apple() { // TODO Auto-generated constructor stub } }
桔子类:
public class Orange extends Fruits { public Orange(String name) { super(name); } public Orange() { // TODO Auto-generated constructor stub } }
下面是作为缓冲区盘子的代码
public class CriticalResources { private int index = 0; private static Fruits[] fruites = new Fruits[1];// 默认临界区有五个商品 private ProducerApple pa = new ProducerApple(this); private ProducerOrange po = new ProducerOrange(this); private ConsumerApple ca = new ConsumerApple(this); private ConsumerOrange co = new ConsumerOrange(this); /** * 向临界资源里添加商品 利用synchronized关键字实现同步 添加后数组指针+1 * 如果临界资源数组里面装满了商品不能再生产,则生产线程等待以便让消费者消费 * * @param goods */ public synchronized void push(Fruits goods) { // while (this.index == this.fruites.length) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notifyAll();// 唤醒生产者 this.fruites[index++] = goods; } /** * 从临界资源里拿商品,先减一后返回 如果index==0说明, 临界资源数组里面没有商品,不能在消费 消费线程阻塞, 让生产者生产 则让生产者 * * @return */ public synchronized Fruits pop() { while (this.index == 0) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notifyAll();// 唤醒消费者 return fruites[--index]; } /** * 看看是不是空了 * * @return */ public synchronized Fruits peek() { if (this.index == 0) return null; else return fruites[index - 1]; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public Fruits[] getFruites() { return fruites; } }
下面是生产桔子和消费桔子的代码
/** * 生产苹果的生产者 * * @author Arthur * */ public class ProducerApple implements Runnable { private CriticalResources cr = null;// 封装一个临界资源对象,以便生产 public ProducerApple(CriticalResources cr) { super(); this.cr = cr; } private int count = 5; @Override public void run() { while (count-- > 0) synchronized (cr) { while ((cr.peek() != null)) { try { cr.wait();// 缓冲区满,该生产者等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 如果不加锁,此处容易被打断 Fruits fruits = new Apple("苹果"); cr.push(fruits); System.out.println("苹果生产商生产了" + fruits); cr.notifyAll(); } } }
/** * 消费苹果的消费者 * * @author Arthur * */ public class ConsumerApple implements Runnable { private CriticalResources cr = null;// 封装一个临界资源对象,以便消费 public ConsumerApple(CriticalResources cr) { super(); this.cr = cr; } int count = 5; @Override public void run() { while(count-->0) synchronized (cr) { while (!(cr.peek() instanceof Apple) ) { try { cr.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } Fruits fruits = cr.pop(); System.out.println("----苹果消费者消费了-------" + fruits); cr.notifyAll(); } } }
桔子生产者与消费者代码:
public class ProducerOrange implements Runnable { CriticalResources cr = null; public ProducerOrange(CriticalResources cr) { super(); this.cr = cr; } int count = 5; //做5次 @Override public void run() { while(count-->0) synchronized (cr) { while (cr.peek() != null) { try { cr.wait();// 该生产这等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Fruits fruits = new Orange("橘子"); cr.push(fruits); System.out.println("橘子生产商生产了" + fruits); cr.notifyAll(); } } }
/** * 消费橘子的消费者 * * @author Administrator * */ public class ConsumerOrange implements Runnable { private CriticalResources cr = null;// 封装一个临界资源对象,以便消费 public ConsumerOrange(CriticalResources cr) { super(); this.cr = cr; } int count = 5; @Override public void run() { while (count-- > 0) // 如果缓冲区是苹果 synchronized (cr) { while (!(cr.peek() instanceof Orange)) { try { cr.wait();// 该消费者等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Fruits fruits = cr.pop(); System.out.println("----橘子消费者消费了-------" + fruits); cr.notifyAll(); } } }
客户端代码
public class Client { /** * @param args */ public static void main(String[] args) { CriticalResources cr = new CriticalResources(); // 生产苹果实例 ProducerApple appleP = new ProducerApple(cr); // 消费苹果实例 ConsumerApple appleC = new ConsumerApple(cr); // 橘子生产者实例 ProducerOrange orangeP = new ProducerOrange(cr); // 橘子消费者实例 ConsumerOrange orangeC = new ConsumerOrange(cr); // 生产苹果线程 Thread pThread = new Thread(appleP); // 消费苹果线程 Thread cThread = new Thread(appleC); // 生产橘子线程 Thread pt = new Thread(orangeP); // 消费橘子线程 Thread ct = new Thread(orangeC); pThread.start(); cThread.start(); pt.start(); ct.start(); } }
运行结果
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
苹果生产商生产了苹果
----苹果消费者消费了-------苹果
橘子生产商生产了橘子
----橘子消费者消费了-------橘子
================================================================================================================================
二、扩展
以上代码中的苹果生产者、消费者,桔子生产者、消费者的类中的run()函数中的每次循环都会调用cr.notifyAll();
我试着把这代去掉,发现运行结果是:
苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子
这是为什么呢?
(1) 我们先来看SDK对这个API的解释。
notifyAll用于唤醒在这个对象上等待的线程。一个线程通过调用等待方法来等待对象的监视器。
被唤醒的线程将会以和其它可能完成此对象的同步的线程相同的方式完成.
for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
(2)网上资料:
在java多线程编程中,就要涉及到了对于资源的访问,当多个线程同时访问一个资源的时候就要涉及到一种访问策略。java提供了锁的机制,就是一个线程访问这个资源的时候可以先把这个资源锁住可以用synchronized(the object)来锁定the object,其他访问这个资源的线程就进入阻塞状态,直到当前的线程执行了这个对象的notify或者notifyall其他访问这个对象的阻塞状态的线程才有可能变成就绪状态。其中notify是唤醒一个线程,而notifyall是唤醒所有阻塞进程。
相关文章推荐
- 生产者消费者之爸爸妈妈儿子女儿苹果橘子编程实现
- 生产者消费者之爸爸妈妈儿子女儿苹果橘子编程实现
- Linux互斥与同步应用(三):posix线程实现单个生产者和单个消费者模型
- 生产者-消费者问题实现 (linux下C同步信号量和互斥信号量的应用)
- Java实现同步机制(生产者消费者)
- 并发编程--在同步代码中使用条件实现生产者消费者
- 基于Java自带同步机制实现生产者-消费者模式
- 用java实现的生产者与消费者多线程同步互斥模型
- Java实现生产者与消费者的同步
- 多生产者--多消费者 显示锁实现同步 java实现
- (十六)java并发编程--线程的死锁解决方案(生产者和消费者几种实现方式)
- Java实现同步机制(生产者消费者)
- Java实现生产者与消费者(四)(多生产者与多消费者使用lock同步锁)
- java多线程实现生产者/消费者同步
- 进程同步-生产者和消费者(PV操作实现——java多线程模拟)
- Java线程间同步实现生产者-消费者模式
- Java Note: 多线程的同步(互斥锁)的方法对比,信号量锁,读写锁的实现,生产者-消费者模式的实现
- Java Note: 多线程的同步(互斥锁)的方法对比,信号量锁,读写锁的实现,生产者-消费者模式的实现
- 关于网宿厦门研发中心笔试的一道PV操作题:利用java中的多线程实现生产者与消费者的同步问题
- Java Note: 多线程的同步(互斥锁)的方法对比,信号量锁,读写锁的实现,生产者-消费者模式的实现