生产者与消费者问题
- 经典生产者与消费者问题
- 生产者不断的往仓库中存放产品,消费者从仓库中消费产品。
- 其中生产者和消费者都可以有若干个。
- 仓库规则:容量有限,库满时不能存放,库空时不能取产品 。
/*
首先定义产品类:
产品类可简单可复杂这里我就以简单的产品id和产品名字来定义产品类
package product;
/** - 产品类
*/
class Product {
private int id;// 产品id
private String name;// 产品名称
public Product(int id, String name) {
this.id = id;
this.name = name;
}
public String toString() {
return "(产品ID:" + id + " 产品名称:" + name + ")";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
以上就是产品类的相关内容
接下来是生产者(这里我使用的类都是继承了Runnable方法)
/**
- 生产者
*/
class Producer implements Runnable {
private Storage storage;//这个是仓库类(在下文实现)
public Producer(Storage storage) {
this.storage = storage;
}
@Override
public void run() {
int i = 0;
Random r = new Random();
while(i<10)//为什么这里是10,因为我定义的仓库大小就是10,详见下文
{
i++;
Product product = new Product(i, “电话” + r.nextInt(100));
storage.push(product);//这里的方法统统都在下面
}
}
}
这是消费者:
/**## 标题
-
消费者
*/
class Consumer implements Runnable {
private Storage storage;
public Consumer(Storage storage) {
this.storage = storage;
}public void run() {
int i = 0;
while(i<10)
{
i++;
storage.pop();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}}
}
到了重头戏的仓库类了,下面的内容有一些小小的难度,不过我相信看到这篇博客的大佬,一定难不住你,一起来看看吧
首先我们要先知道仓库的主要功能,首先仓库功能要有存储产品功能(在这里我把消费功能写到了仓库中,等下会着重告诉)
代码如下:
/**
*仓库
*/
class Storage {
// 仓库容量为10
private Product[] products = new Product[10];
private int top = 0;
// 生产者往仓库中放入产品
public synchronized void push(Product product)//这个方法执行一次就会生产一个商品
//这里说一下sychronized是线程锁关键字
简单来说就是只有一个线程能执行,在执行时其他线程必须等待,不得干扰
{
while (top == products.length) {
try {
System.out.println(“producer wait”);
wait();//仓库已满,等待
} catch (InterruptedException e) {
}
}
//把产品放入仓库
products[top++] = product;
System.out.println(Thread.currentThread().getName() + " 生产了产品"
+ product);
System.out.println(“producer notifyAll”);
notifyAll();//唤醒等待线程
}
接下来是消费的方法:
// 消费者从仓库中取出产品
public synchronized Product pop() {
while (top == 0) {
try {
System.out.println(“consumer wait”);
wait();//仓库空,等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//从仓库中取产品
–top;
Product p = new Product(products[top].getId(), products[top].getName());
products[top] = null;
System.out.println(Thread.currentThread().getName() + " 消费了产品" + p);
System.out.println(“comsumer notifyAll”);
notifyAll();//唤醒等待线程
return p;
}
}
至此我们的生产者消费者的四个类(生产者,消费者,商品,仓库)就已经完成了
接下来就让我们编写一个测试类:
public class ProductTest {
public static void main(String[] args) throws InterruptedException {
Storage storage = new Storage();Thread consumer1 = new Thread(new Consumer(storage)); consumer1.setName("消费者1"); Thread consumer2 = new Thread(new Consumer(storage)); consumer2.setName("消费者2"); Thread producer1 = new Thread(new Producer(storage)); producer1.setName("生产者1"); Thread producer2 = new Thread(new Producer(storage)); producer2.setName("生产者2"); producer1.start(); producer2.start(); Thread.sleep(1000); consumer1.start(); consumer2.start(); //注意在这里呢你可能执行之后看到结果会很懵,我就来给你解释一下: 首先呢我先让生产者来执行(我已经提前规定好了仓库的大小只能为10)所以生产者的两个线程在生产了10个商品 之后就会退出执行,然后休眠1秒钟之后消费者就会参与其中执行)
}