Java对象锁-通俗理解生产者消费者问题

生产者-消费者是一个十分经典的多线程并发协作的模式,所谓生产者-消费者问题,实际上主要是包含了两类线程,一类是生产者线程用于源源不断生产数据,另一类是消费者线程用于消费数据,为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库,生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为;而消费者只需要从共享数据区中拿数据,不需要关心生产者的行为。生产者唯一关心的就是仓库是否有空余地方,而消费者唯一关系的就是仓库中是否有东西可拿。

废话不说直接上代码(csdn的编辑器特么就像一坨屎一样,代码都没法对齐)

package com.java.test.model;

//仓库类
public class Storehouse {
	private int capacity;	//容量
	private int count = 0;	//当前物品数
	private String name;
	private String[] goods;	//商品数组

	public Storehouse(String name, int capacity) {
	    this.name = name;
            this.capacity = capacity;
	    goods = new String[capacity];
	    System.out.println(this.name+"->初始化仓库...");
	}

	//添加一个物品
	public void add(String name) {
	    goods[count] = name;
	    count++;
	}

	//移除一个物品
	public String remove() {
            count--;
            return goods[count];
	}

	public int getCount() {
            return count;
	}
	
	public int getCapacity(){
	    return capacity;
	}
}
package com.java.test.model;

public class Producer {
	private String name;
	private String[] productType;
	private boolean isRun = false;

	/**
	 * @param name
	 *            生产者名称
	 * @param productType
	 *            产品种类
	 */
	public Producer(String name, String[] productType) {
		this.name = name;
		this.productType = productType;
	}

	public void start(Storehouse storehouse) {
		isRun = true;
		System.out.println(this.name + "->开始生产");
		Thread thread = new Thread(() -> {
			while (isRun) {
				try {
					synchronized (storehouse) { // 拿到仓库对象的锁(也可理解为现实中的门钥匙)
						if (storehouse.getCapacity() == storehouse.getCount()) {// 如果最大容量等于库存量,则等待消费者消费
							storehouse.wait();
						} else {
							String goodName = getProduct(); // 生产一个产品并且放入仓库中
							storehouse.add(goodName);
							System.out.println(this.name + "->生产了一个 " + goodName + ", 剩余 " + storehouse.getCount());
							storehouse.notifyAll(); // 唤醒所有等待仓库对象的进程
						}
					}
					Thread.sleep(10); // 休息10毫秒
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			System.out.println(this.name + "->生产结束");

		});
		thread.start();
	}

	// 停止生产
	public void stop() {
		isRun = false;
	}

	/**
	 * 模拟随机生产水果
	 * @return
	 */
	private String getProduct() throws InterruptedException {
		int random = (int) (Math.random() * 10) % productType.length;
		Thread.sleep(20);
		return productType[random];
	}
}
package com.java.test.model;

//消费者类
public class Consumer {
	private String name;
	private boolean isRun = false;

	public Consumer(String name) {
		this.name = name;
	}

	public void start(Storehouse storehouse) {
		isRun = true;
		System.out.println(this.name + "->开始消费");
		Thread thread = new Thread(() -> {
			while (isRun) {
				try {
					synchronized (storehouse) {
						if (storehouse.getCount() == 0) { //仓库如果为空,则等待
							storehouse.wait();
						} else {
							String goodName = storehouse.remove();
							System.out.println(this.name + "->消费了一个 " + goodName + ", 剩余 " + storehouse.getCount());
							storehouse.notifyAll();	//唤醒所有等待仓库对象的进程
						}
					}
					Thread.sleep(25); //休息25毫秒
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			System.out.println(this.name + "->消费结束");
		});

		thread.start();
	}

	//停止消费
	public void stop() {
		isRun = false;
	}
}
package com.java.test;

import com.java.test.model.Consumer;
import com.java.test.model.Producer;
import com.java.test.model.Storehouse;

public class Main {
	public static void main(String[] args) {
		Consumer consumer1 = new Consumer("消费者1");
		Consumer consumer2 = new Consumer("消费者2");
		Consumer consumer3 = new Consumer("消费者3");
		Consumer consumer4 = new Consumer("消费者4");
		
		Producer producer1 = new Producer("生产者1", new String[]{"苹果","香蕉","甘蔗"});
		Producer producer2 = new Producer("生产者2",new String[]{"苹果","香蕉","荔枝","甘蔗"});
		
		Storehouse storehouse = new Storehouse("水果仓库", 50);
		
		//开始运作
		producer1.start(storehouse);
		consumer1.start(storehouse);
		producer2.start(storehouse);
		consumer2.start(storehouse);
		consumer3.start(storehouse);
		consumer4.start(storehouse);
	}
}
运行结果
标题
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值