在《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) {
//相应中断,继续执行while(循环),可能就要跳出去
}
}
this.notifyAll();// 唤醒生产者
this.fruites[index++] = goods;
}
/**
* 从临界资源里拿商品,先减一后返回 如果index==0说明, 临界资源数组里面没有商品,不能在消费 消费线程阻塞, 让生产者生产 则让生产者
*
* @return
*/
public synchronized Fruits pop() {
while (this.index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
//相应中断,继续执行while(循环),可能就要跳出去
}
}
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;
}
}
下面是生产桔子和消费桔子的代码
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();
}
}
}
下面是生产苹果核消费苹果的代码
package arthur.thread.producerandcoustomer;
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){
//响应中断
}
} /如果不加锁,此处容易被打断
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) {
//相应中断
}
}
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();
}
}
运行结果
苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子 苹果生产商生产了苹果 ----苹果消费者消费了-------苹果 橘子生产商生产了橘子 ----橘子消费者消费了-------橘子