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

java线程之生产者消费者问题

2013-07-26 11:07 375 查看
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();// new一个容器用于装窝头
Producer p = new Producer(ss);// new一个生产者线程,参数指明往哪个容器内生产
Consumer c = new Consumer(ss);// new一个消费者线程,参数指明从哪个容器内消费
// 上面两个线程访问的是同一个容器对象
new Thread(p).start();// 启动两个线程
new Thread(c).start();
}

}

// 实现窝头类
class WoTou {
int id;// 给每个窝头一个标记

WoTou(int id) {// 写其构造方法,传递的参数是将被新建的对象的id
this.id = id;
}

public String toString() {// 重写其toString方法,用于下面将对象输出
return "WoTou" + id;
}
}

// 实现容器类,先进后出,stack
class SyncStack {
int index = 0;// 用index标记现在装到第几个了
static int num = 0;// 用于统计容器中共有几个窝头
WoTou[] arrWT = new WoTou[6];// 用一个对象数组来模拟容器,该容器只能装WoTou类对象,设置容量为6

// 实现往容器中放窝头的方法
public synchronized void push(WoTou wt) {// 传递的参数是WoTou类对象wt
while (num == arrWT.length) {// 如果当前容器满了,wait
try {
System.out.println("满了,请消费!!");
this.wait();// 让锁定当前对象的当前线程wait,并释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
arrWT[index] = wt;// 将窝头装进容器
num += 1;// 窝头数加1
System.out.println("往容器里放进了" + wt);
System.out.println("当前容器里有" + num + "个窝头");
index++;// 标记移向下一位置
this.notify();// 放进的动作完成后,叫醒一个现在正在wait在这个对象上的线程
}

// 实现拿出窝头的方法
public synchronized void pop() {
while (num == 0) {// 如果当前容器空了,wait
try {
System.out.println("空了,请生产!!");
this.wait();// 让锁定当前对象的当前线程wait,并释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index--;// 标记移向前一位置
num -= 1;// 窝头数减1
System.out.println("从容器里拿出了" + arrWT[index]);
System.out.println("消费了:" + arrWT[index]);
System.out.println("当前容器里有" + num + "个窝头");
this.notify();// 拿出的动作完成后,叫醒一个现在正在wait在这个对象上的线程
}
}

// 实现生产者类
class Producer implements Runnable {
SyncStack ss = null;// 新建容器用于装窝头

Producer(SyncStack ss) {// 实现其构造函数,指明往哪个容器里生产
this.ss = ss;
}

public void run() {// 实现Runnable接口就必须重写其run方法
for (int i = 0; i < 20; i++) {// 假设每个生产者最多生产20个窝头
WoTou wt = new WoTou(i); // 调用WoTou类的构造方法生产窝头wt,传递的参数是wt的id
System.out.println("生产了:" + wt);// 每生产一个就打印一句,输出对象wt的时候,其实是输出object的toString方法返回的值
ss.push(wt);// 调用容器ss的push方法将窝头wt放进容器ss,传递的参数是WoTou类对象wt
try {
Thread.sleep((int) (Math.random() * 2));// 生产一个后睡眠一下
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

// 实现消费者类
class Consumer implements Runnable {
SyncStack ss = null; // 指明从哪个容器里消费

Consumer(SyncStack ss) { // 指明到哪个容器里消费
this.ss = ss;
}

public void run() { // 实现Runnable接口就必须重写其run方法
for (int i = 0; i < 20; i++) { // 假设每个消费者最多消费20个窝头
ss.pop(); // 调用容器对象ss的pop方法消费窝头,pop方法的返回值是一个WoTou类对象

try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


执行结果有如下两种类型:
类型一:
生产了:WoTou0

往容器里放进了WoTou0

当前容器里有1个窝头

生产了:WoTou1

往容器里放进了WoTou1

当前容器里有2个窝头

生产了:WoTou2

往容器里放进了WoTou2

当前容器里有3个窝头

生产了:WoTou3

往容器里放进了WoTou3

当前容器里有4个窝头

从容器里拿出了WoTou3

消费了:WoTou3

当前容器里有3个窝头

生产了:WoTou4

往容器里放进了WoTou4

当前容器里有4个窝头

生产了:WoTou5

往容器里放进了WoTou5

当前容器里有5个窝头

生产了:WoTou6

往容器里放进了WoTou6

当前容器里有6个窝头

生产了:WoTou7

满了,请消费!!

从容器里拿出了WoTou6

消费了:WoTou6

当前容器里有5个窝头

往容器里放进了WoTou7

当前容器里有6个窝头

生产了:WoTou8

满了,请消费!!

从容器里拿出了WoTou7

消费了:WoTou7

当前容器里有5个窝头

往容器里放进了WoTou8

当前容器里有6个窝头

生产了:WoTou9

满了,请消费!!

从容器里拿出了WoTou8

消费了:WoTou8

当前容器里有5个窝头

往容器里放进了WoTou9

当前容器里有6个窝头

生产了:WoTou10

满了,请消费!!

从容器里拿出了WoTou9

消费了:WoTou9

当前容器里有5个窝头

往容器里放进了WoTou10

当前容器里有6个窝头

生产了:WoTou11

满了,请消费!!

从容器里拿出了WoTou10

消费了:WoTou10

当前容器里有5个窝头

往容器里放进了WoTou11

当前容器里有6个窝头

生产了:WoTou12

满了,请消费!!

从容器里拿出了WoTou11

消费了:WoTou11

当前容器里有5个窝头

往容器里放进了WoTou12

当前容器里有6个窝头

生产了:WoTou13

满了,请消费!!

从容器里拿出了WoTou12

消费了:WoTou12

当前容器里有5个窝头

往容器里放进了WoTou13

当前容器里有6个窝头

生产了:WoTou14

满了,请消费!!

从容器里拿出了WoTou13

消费了:WoTou13

当前容器里有5个窝头

往容器里放进了WoTou14

当前容器里有6个窝头

生产了:WoTou15

满了,请消费!!

从容器里拿出了WoTou14

消费了:WoTou14

当前容器里有5个窝头

往容器里放进了WoTou15

当前容器里有6个窝头

生产了:WoTou16

满了,请消费!!

从容器里拿出了WoTou15

消费了:WoTou15

当前容器里有5个窝头

往容器里放进了WoTou16

当前容器里有6个窝头

生产了:WoTou17

满了,请消费!!

从容器里拿出了WoTou16

消费了:WoTou16

当前容器里有5个窝头

往容器里放进了WoTou17

当前容器里有6个窝头

生产了:WoTou18

满了,请消费!!

从容器里拿出了WoTou17

消费了:WoTou17

当前容器里有5个窝头

往容器里放进了WoTou18

当前容器里有6个窝头

生产了:WoTou19

满了,请消费!!

从容器里拿出了WoTou18

消费了:WoTou18

当前容器里有5个窝头

往容器里放进了WoTou19

当前容器里有6个窝头

从容器里拿出了WoTou19

消费了:WoTou19

当前容器里有5个窝头

从容器里拿出了WoTou5

消费了:WoTou5

当前容器里有4个窝头

从容器里拿出了WoTou4

消费了:WoTou4

当前容器里有3个窝头

从容器里拿出了WoTou2

消费了:WoTou2

当前容器里有2个窝头

从容器里拿出了WoTou1

消费了:WoTou1

当前容器里有1个窝头

从容器里拿出了WoTou0

消费了:WoTou0

当前容器里有0个窝头

类型二:
生产了:WoTou0

空了,请生产!!


往容器里放进了WoTou0

当前容器里有1个窝头

从容器里拿出了WoTou0

消费了:WoTou0

当前容器里有0个窝头

生产了:WoTou1

往容器里放进了WoTou1

当前容器里有1个窝头

生产了:WoTou2

往容器里放进了WoTou2

当前容器里有2个窝头

生产了:WoTou3

往容器里放进了WoTou3

当前容器里有3个窝头

生产了:WoTou4

往容器里放进了WoTou4

当前容器里有4个窝头

生产了:WoTou5

往容器里放进了WoTou5

当前容器里有5个窝头

生产了:WoTou6

往容器里放进了WoTou6

当前容器里有6个窝头

生产了:WoTou7

满了,请消费!!

从容器里拿出了WoTou6

消费了:WoTou6

当前容器里有5个窝头

往容器里放进了WoTou7

当前容器里有6个窝头

生产了:WoTou8

满了,请消费!!

从容器里拿出了WoTou7

消费了:WoTou7

当前容器里有5个窝头

往容器里放进了WoTou8

当前容器里有6个窝头

生产了:WoTou9

满了,请消费!!

从容器里拿出了WoTou8

消费了:WoTou8

当前容器里有5个窝头

往容器里放进了WoTou9

当前容器里有6个窝头

生产了:WoTou10

满了,请消费!!

从容器里拿出了WoTou9

消费了:WoTou9

当前容器里有5个窝头

往容器里放进了WoTou10

当前容器里有6个窝头

生产了:WoTou11

满了,请消费!!

从容器里拿出了WoTou10

消费了:WoTou10

当前容器里有5个窝头

往容器里放进了WoTou11

当前容器里有6个窝头

生产了:WoTou12

满了,请消费!!

从容器里拿出了WoTou11

消费了:WoTou11

当前容器里有5个窝头

往容器里放进了WoTou12

当前容器里有6个窝头

生产了:WoTou13

满了,请消费!!

从容器里拿出了WoTou12

消费了:WoTou12

当前容器里有5个窝头

往容器里放进了WoTou13

当前容器里有6个窝头

生产了:WoTou14

满了,请消费!!

从容器里拿出了WoTou13

消费了:WoTou13

当前容器里有5个窝头

往容器里放进了WoTou14

当前容器里有6个窝头

生产了:WoTou15

满了,请消费!!

从容器里拿出了WoTou14

消费了:WoTou14

当前容器里有5个窝头

往容器里放进了WoTou15

当前容器里有6个窝头

生产了:WoTou16

满了,请消费!!

从容器里拿出了WoTou15

消费了:WoTou15

当前容器里有5个窝头

往容器里放进了WoTou16

当前容器里有6个窝头

生产了:WoTou17

满了,请消费!!

从容器里拿出了WoTou16

消费了:WoTou16

当前容器里有5个窝头

往容器里放进了WoTou17

当前容器里有6个窝头

生产了:WoTou18

满了,请消费!!

从容器里拿出了WoTou17

消费了:WoTou17

当前容器里有5个窝头

往容器里放进了WoTou18

当前容器里有6个窝头

生产了:WoTou19

满了,请消费!!

从容器里拿出了WoTou18

消费了:WoTou18

当前容器里有5个窝头

往容器里放进了WoTou19

当前容器里有6个窝头

从容器里拿出了WoTou19

消费了:WoTou19

当前容器里有5个窝头

从容器里拿出了WoTou5

消费了:WoTou5

当前容器里有4个窝头

从容器里拿出了WoTou4

消费了:WoTou4

当前容器里有3个窝头

从容器里拿出了WoTou3

消费了:WoTou3

当前容器里有2个窝头

从容器里拿出了WoTou2

消费了:WoTou2

当前容器里有1个窝头

从容器里拿出了WoTou1

消费了:WoTou1

当前容器里有0个窝头

发现第二种类型的第二句输出是错误的,出错原因在哪儿呢?该怎么解决呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: