欢迎来到HugNew-拥抱变化,扫一扫右边二维码关注微信订阅号:Martin说 或 加QQ群:427697041互相交流,Stay hungry, Stay foolish.

java多线程同步:生产者与消费者问题

并发 Martin 1549℃ 0评论

生产者与消费者问题问题是线程同步里边一个很经典的问题。

用通俗的语言来描述:一群生产者不断的生产产品,并将产品放到一个容器里边;同时一群消费者不断从容器里边消费产品。

容器的容量是有限的。如果容器满了,生产者不能再往容器放产品,必须进入等待状态。等待产品被消费者拿走了,再往容器放产品。

同样,如果容器空了,消费者也必须进入等待状态。等待生产者往里边放产品,再将消费者唤醒。

下边我们来看看如何用java代码来实现

我们假设生产者是一群厨师,产品是面包,容器是一个篮子,消费者是一群消费者。

用面向对象的思维来考虑,我们要至少要定义4个类

先定义好面包类

/*
 *面包类,用于存放厨师生产的面包

 */

public class Bread {

private String producer;

 

public Bread(String producer) {

super();

this.producer = producer;

}

 

@Override

public String toString() {

return producer;

}

}

再定义一个篮子类x

/*

 * 篮子类,用于存放面包

 * 篮子假定最多放10个面包

 */

public class Basket {

private int index = 0;

private Bread[] arrayBread = new Bread[10];

 

/*

     * 此方法用于往篮子里扔面包 每当厨师生成好一个面包就往篮子里边扔 由于当某一个厨师在往篮子扔面包的过程(还没扔完,但是面包已经在篮子里),

     * 又有一个厨师要往篮子里扔面包。 如果这是篮子里已经有9个面包的话,最后一个厨师就不能在扔了。

     * 所以需要给这个方法加把锁,等一个厨师扔完后,另外一个厨师才能往篮子里扔。

     */

public synchronized void push(int id, Bread bread) {

System.out.println("生成前篮子里有面包:" + index + " 个");

// 当厨师发现篮子满了,就在那里不停的等着

while (index == arrayBread.length) {

System.out.println("篮子满了,我开始等等。。。。。。");

try {

// 厨师(一个生产线程)开始不停等待

// 他需要等待顾客(一个消费线程)把它叫醒

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

// 唤醒一个正在等待的线程,如果唤醒的线程为生产线程,则又会进入等待状态,

// 如果为消费线程,则因生产线程生产了面包的缘故,消费线程可以进行消费

this.notify();

arrayBread[index] = bread;

index++;

System.out.println(bread);

 

}

 

/*

     * 此方法用于往篮子里拿面包 加锁原因和上边一样

     */

public synchronized Bread pop(int id) {

System.out.println("消费前篮子里有面包:" + index + " 个");

while (index == 0) {

System.out.println("篮子空了,我开始等等。。。。。。");

try {

// 顾客(一个消费线程)开始不停等待

// 他需要等待厨师(一个生产线程)把它叫醒

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

// 唤醒一个正在等待的线程,如果唤醒的线程为消费线程,则又会进入等待状态,

// 如果为生产线程,则因生产线程消费了面包的缘故,生产线程可以进行生产

this.notify();

index--;

System.out.println("第" + id + "个顾客消费了 -->" + arrayBread[index]);

return arrayBread[index];

}

}

再定义一个厨师类

/*

 * 厨师类,用于生产面包

 */

public class Kitchener implements Runnable {

private Basket basket;

private int id;

 

public Kitchener(int id,Basket basket) {

super();

this.id = id;

this.basket = basket;

}

 

@Override

public void run() {

//让厨师生产10个面包

for (int i = 1; i <= 10; i++) {

Bread bread = new Bread("第" + id + "个厨师生成的面包");

basket.push(id,bread);

 

 

try {

Thread.sleep(1);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

}

 

}

最后定义顾客类

/*

 * 顾客类,用于消费面包

 */

public class Customer implements Runnable {

private Basket basket;

private int id;

public Customer(int id,Basket basket) {

super();

this.id = id;

this.basket = basket;

}

 

@Override

public void run() {

// 让顾客消费10个面包

for (int i = 1; i <= 10; i++) {

basket.pop(id);

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

}

 

}

好我们就可以来测试一下代码

public class Test {

public static void main(String[] args) {

Basket basket = new Basket();

// 两个厨师两个客户

Kitchener kitchener1 = new Kitchener(1,basket);

Kitchener kitchener2 = new Kitchener(2,basket);

Customer customer1 = new Customer(1,basket);

Customer customer2 = new Customer(2,basket);

new Thread(kitchener1).start();

new Thread(kitchener2).start();

new Thread(customer1).start();

new Thread(customer2).start();

}

 

}

运行结果

生成前篮子里有面包:0 个
第1个厨师生成的面包

消费前篮子里有面包:1 个

第2个顾客消费了 -->第1个厨师生成的面包

消费前篮子里有面包:0 个

篮子空了,我开始等等。。。。。。

生成前篮子里有面包:0 个

第2个厨师生成的面包

第1个顾客消费了 -->第2个厨师生成的面包

生成前篮子里有面包:0 个

第2个厨师生成的面包

生成前篮子里有面包:1 个

第1个厨师生成的面包

生成前篮子里有面包:2 个

第2个厨师生成的面包

生成前篮子里有面包:3 个

第1个厨师生成的面包

生成前篮子里有面包:4 个

第2个厨师生成的面包

生成前篮子里有面包:5 个

第1个厨师生成的面包

生成前篮子里有面包:6 个

第2个厨师生成的面包

生成前篮子里有面包:7 个

第1个厨师生成的面包

生成前篮子里有面包:8 个

第2个厨师生成的面包

生成前篮子里有面包:9 个

第1个厨师生成的面包

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第2个顾客消费了 -->第1个厨师生成的面包

第2个厨师生成的面包

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第1个顾客消费了 -->第2个厨师生成的面包

第1个厨师生成的面包

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第2个顾客消费了 -->第1个厨师生成的面包

第2个厨师生成的面包

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第1个顾客消费了 -->第2个厨师生成的面包

第1个厨师生成的面包

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第1个顾客消费了 -->第1个厨师生成的面包

第2个厨师生成的面包

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第2个顾客消费了 -->第2个厨师生成的面包

第1个厨师生成的面包

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

生成前篮子里有面包:10 个

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第1个顾客消费了 -->第1个厨师生成的面包

第2个厨师生成的面包

篮子满了,我开始等等。。。。。。

消费前篮子里有面包:10 个

第2个顾客消费了 -->第2个厨师生成的面包

第1个厨师生成的面包

消费前篮子里有面包:10 个

第1个顾客消费了 -->第1个厨师生成的面包

消费前篮子里有面包:9 个

第2个顾客消费了 -->第2个厨师生成的面包

消费前篮子里有面包:8 个

第1个顾客消费了 -->第1个厨师生成的面包

消费前篮子里有面包:7 个

第2个顾客消费了 -->第2个厨师生成的面包

消费前篮子里有面包:6 个

第1个顾客消费了 -->第1个厨师生成的面包

消费前篮子里有面包:5 个

第2个顾客消费了 -->第2个厨师生成的面包

消费前篮子里有面包:4 个

第1个顾客消费了 -->第1个厨师生成的面包

消费前篮子里有面包:3 个

第2个顾客消费了 -->第2个厨师生成的面包

消费前篮子里有面包:2 个

第1个顾客消费了 -->第1个厨师生成的面包

消费前篮子里有面包:1 个

第2个顾客消费了 -->第2个厨师生成的面包

来源:csdn

相关:

阿里的java实习生岗位的一个笔试题:

用Java代码模拟实现:一个人不断往箱子里放苹果,另一个人不断从箱子里取苹果,箱子只能放5个苹果,苹果数量无限。要求不使用java.util.concurrent包中的类。

转载请注明:HugNew » java多线程同步:生产者与消费者问题

喜欢 (3)or分享 (0)
发表我的评论
取消评论

表情