您的位置:首页 > 编程语言 > Java开发

JAVA多线程实例(生产者与消费者问题)

2010-04-03 09:14 851 查看
昨天复习JAVA多线程知识的时候,重新写了一下生产者与消费者的问题,其中发现了很多需要注意的地方。所以把代码发出来,分享给刚入门的哥们儿,如果你的老鸟,请多多指正,欢迎拍砖!

问题描述:在一个面包店中,有一个做面包的师傅和两个卖面包的服务员,生产面包的原料是固定的,装面包的容器也是固定大小的,但是做面包的次数(有一定的范围)与卖面包的个数都是随机生成的(有一定的范围)。

主程序类

public class Main {
/*
* author JuneHe
* email emailxiaojun@sina.com
*
* 一个生产者,两个消费者的多线程问题
* 生产次数,与销售次数随机生成
* 生产原料固定,生产量有限制
*/
public static void main(String[] args) {
Seller s = new Seller();
Maker m  = new Maker();
Thread tm = new Thread(m);
Thread ts1 = new Thread(s);
Thread ts2 = new Thread(s);
s.setTm(tm);
m.setTs(ts1,ts2);
System.out.println(m+"要做"+m.num+"次");
System.out.println(s+"要做"+Seller.num+"次");
tm.start();
ts1.start();
ts2.start();
}
}


面包容器管理类

import java.util.Random;

public class BreadBox {
public static Object lockob = new Object();
public static Random r = new Random();
public static final int breakcountlimit = 10; //限制数
public static int breadmateral = 15; //面包原料数
public static int breadcount = 5; //原始面包数
}


面包师傅类

public class Maker implements Runnable {

public Thread ts1 = null;
public Thread ts2 = null;
public int num = BreadBox.r.nextInt(50)+1; //随机的控制生产次数

public boolean flag = true;

public void setTs(Thread ts1,Thread ts2) {
this.ts1 = ts1;
this.ts2 = ts2;
}

public void run() {
while (flag&&num>0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
make();
}
System.out.println(toString()+"不做了!");
}

public void make() {
synchronized (BreadBox.lockob) {

while(BreadBox.breadmateral!=0) {
if(!(ts1.isAlive()||ts2.isAlive())){

if(BreadBox.breadcount>=BreadBox.breakcountlimit) {
System.out.println("销售员不卖了,有原料但是盒子装不下了!");
this.flag = false;
return;
} else {
BreadBox.breadcount++;
BreadBox.breadmateral--;
this.num--;
System.out.println(toString()+"做了一个面包! 再做"+(BreadBox.breakcountlimit-BreadBox.breadcount)+"个就盒子装不下了");

//由于改变了自己执行的次数所以做完操作后要判断!
if(this.num==0) {
System.out.println(toString()+"制作次数到了马上不做了!");
BreadBox.lockob.notifyAll(); //不做之前要先通知其他线程!
return;
}

return;
}
} else {
if(BreadBox.breadcount<BreadBox.breakcountlimit) {

BreadBox.breadcount++;
BreadBox.breadmateral--;
this.num--;
System.out.println(toString()+"做了一个面包! 再做"+(BreadBox.breakcountlimit-BreadBox.breadcount)+"个就装不下了");

//由于改变了自己执行的次数所以做完操作后要判断!
if(this.num==0) {
System.out.println(toString()+"制作次数到了马上不做了!");
BreadBox.lockob.notifyAll(); //不做之前要先通知其他线程!
return;
}

return;
} else {
try {
//假如销售员还在卖,但已经达到了次数,则不必等待了
if(Seller.num==0) {
return;
}

System.out.println(toString()+"销售员还在卖,但是装满了!");
BreadBox.lockob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
System.out.println(toString()+"没原料了,马上不做了");
this.flag = false;
BreadBox.lockob.notifyAll(); //没原料了要通知
return;
}
}

public String toString() {
return (int)Thread.currentThread().getId()+":厨师:";
}
}


服务员类

public class Seller implements Runnable {

public Thread tm = null;
public static int num = BreadBox.r.nextInt(50)+1; //随机的控制消费次数
public boolean flag = true;

public void setTm(Thread tm) {
this.tm = tm;
}

public void run() {
while(flag&&num>0) {
try {
Thread.sleep(1000); //卖一次睡一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
sell();
}
System.out.println(toString()+"不卖了!");
}

public void sell() {
synchronized (BreadBox.lockob) {
while(BreadBox.breadcount==0) {
BreadBox.lockob.notifyAll();
if(!tm.isAlive()) {
System.out.println(toString()+"厨师不做了没面包了.");
this.flag = false;
return;
}
else {
try {
System.out.println("厨师还在做但是没面包了." +toString()+"在等待");
BreadBox.lockob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

if(Seller.num==0) {
System.out.println(toString()+"销售次数到了马上不卖了!");
this.flag=false;
BreadBox.lockob.notifyAll();
return;
}

Seller.num--; //自己要卖的次数减一
BreadBox.breadcount--;  //面包数减一
System.out.println(toString()+"已卖出一个面包! 还有面包"+BreadBox.breadcount+"个");
BreadBox.lockob.notifyAll();

//由于改变了自己生存的次数所以做完操作后要判断!
if(Seller.num==0) {
System.out.println(toString()+"销售次数到了马上不卖了!");
this.flag=false;
BreadBox.lockob.notifyAll(); //不做之前要先通知其他线程!
return;
}

return;
}
}

public String toString() {
return (int)Thread.currentThread().getId()+":销售员:";
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: