Java多线程(三)生产者与消费者案例

唤醒与等待

notify():随机唤醒一条线程

notifyAll():唤醒全部线程

wait():让线程进入等待状态

补充:

wait和sleep的区别?

sleep:

  • 可以设定线程的休眠时间,到点自然醒。
  • 如果有锁,那么不释放执行权。
  • 如果没有锁,释放执行权。是Thread的一个静态方法。

wait:

  • 可以指定休眠时间,也可以不指定。
  • 释放锁,并且释放执行权。
  • 是Object的一个对象方法。

经典案例:生产者与消费者案例

无限生产与消费,仓库的总量不得超过1000,每次生产的总量+原有仓库的总量不得超过1000,消费的总量不得超过仓库的总量。

【仓库】

class Count {

	private int counts; // 用于描述生产总量
	private boolean flag; // 用于切换生产与消费状态

	public Count(int counts, boolean flag) {
		this.counts = counts;
		this.flag = flag;
	}

	public int getCounts() {
		return counts;
	}

	public void setCounts(int counts) {
		this.counts = counts;
	}

	public boolean getFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	@Override
	public String toString() {
		return "Count [counts=" + counts + ", flag=" + flag + "]";
	}

}

仓库中,主要存放的是原料总量与切换生产者与消费者状态。

【生产者】

class Producer implements Runnable{

	private Count c;	//仓库总量

	public Producer(Count c) {
		this.c = c;
	}

	public Count getC() {
		return c;
	}

	public void setC(Count c) {
		this.c = c;
	}

	@Override
	public  void run() {
		//设置无限循环
		while(true){
			//设置锁
			synchronized (c) {
				//当为消费者的线程抢到资源的时候进行休眠
				while(c.getFlag()){
					try {
						c.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				//获得最大能生产的总量
				int maxCount = 1000 - c.getCounts();
				//Math.random()方法产生[0,1)之间的随机数
				int newPro = (int) (Math.random()*maxCount);
				//设置新的仓库数量
				c.setCounts(newPro + c.getCounts());
				System.out.println("新生产了" + newPro + "个总量" + ",仓库拥有" + c.getCounts() + "个数量");
				//切换状态
				c.setFlag(true);
				//唤醒全部线程
				c.notifyAll();
			}
		}
	}
}

【消费者】

class Consumer implements Runnable{
	private Count c;	//仓库总量

	public Consumer(Count c) {
		this.c = c;
	}

	public Count getC() {
		return c;
	}

	public void setC(Count c) {
		this.c = c;
	}

	@Override
	public void run() {
		while(true){
			synchronized (c) {
				//当为生产者的线程抢到资源的时候进行休眠
				while(!c.getFlag()){
					try {
						c.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				//获得消费的总量
				int newCon = (int) (Math.random()*c.getCounts());
				//更新仓库原料
				c.setCounts(c.getCounts() - newCon);
				System.out.println("新消费了" + newCon + "个总量" + ",仓库拥有" + c.getCounts() + "个数量");
				//切换线程状态
				c.setFlag(false);
				//唤醒全部线程
				c.notifyAll();
			}
		}
		
	}
}

【测试类】

public static void main(String[] args) {
		Count c = new Count(1000,true);
		new Thread(new Consumer(c)).start();
		new Thread(new Producer(c)).start();
		new Thread(new Consumer(c)).start();
		new Thread(new Producer(c)).start();
	}

开了4个线程去测试。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值