Day20:线程之间的通信-----生产者消费者

博客围绕生产者 - 消费者线程模型展开,介绍了一个生产者与一个消费者、多个生产者与多个消费者的情况。以产品类为例,分五步实现生产一个消费一个的效果,还阐述了‘生产者 - 消费者 - 仓储’模型,明确生产者、消费者在仓储不同状态下的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

案例一:有两个线程,一个生产者线程,一个消费者线程

假设有一个产品类(实体类),我们通过生产者线程对其值(属性)进行设置,通过消费者线程再读取其设置的值。

要达到的最终效果是:每次生产一个,消费一个。

分五步来实现:

第一步,两个线程正确操作同一个数据源

第二步,采用循环实现数据的交替变化(数据在两个产品之间切换),来更明显发现上述程序存在的问题(把潜在问题放大化)

第三步,采用同步机制来解决上述的问题

第四步,考虑如何达到读一个写一个的效果(java的等待唤醒机制 wait notiy)

生产一个消费一个

生产者,发现有产品,就休息一下,等待消费者消费,等消费完,继续生产

消费者,发现没有产品,就休息以下,等待生产者进行生产,生产完了,继续消费

 

第五步,更加合理的优化写法

把原先是否需要wait()的控制由生产者线程(或消费者线程)搬到了产品类里面的同步方法中,调用者只管调用,不需要关注同步的处理细节,就好比下面的理解来看

生产者(厨师)

产品类(服务员-手握决定权)

消费者(顾客)

 

一个生产者一个消费者

public class Test01 {

	public static void main(String[] args) {
		
		Phone phone = new Phone();
		Producer producer = new Producer(phone);
		Consumer consumer = new Consumer(phone);
		
		producer.start();
		consumer.start();	
	}
}

//手机类
public class Phone {
	private String brand;
	private double price;
	private boolean store;
	
	public Phone() {}
	public Phone(String brand, int price) {
		this.brand = brand;
		this.price = price;
	}
	
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}
	
	public double getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	
	public boolean isStore() {
		return store;
	}
	public void setStore(boolean store) {
		this.store = store;
	}
}

//生产者线程
public class Producer extends Thread{
	private Phone phone;
	public Producer(Phone phone) {
		this.phone = phone;
	}
	@Override//重写run方法
	public void run() {
		boolean flag=true;
		while(true) {
			synchronized (phone) {
				if(phone.isStore()==true) {
					try {
						phone.wait();
					} catch (InterruptedException e) {}
				}
				if(flag) {
					phone.setBrand("三星");
					phone.setPrice(4999);
				}else {
					phone.setBrand("小米");
					phone.setPrice(1999);
				}
				flag=!flag;
				phone.setStore(true);
				phone.notify();
			}
		}
	}
}

//消费者线程
public class Consumer extends Thread{
	private Phone phone;
	public Consumer(Phone phone) {
		this.phone = phone;
	}
	@Override
	public void run() {
		while(true) {
			synchronized (phone) {
				if(phone.isStore()==false) {
					try {
						phone.wait();
					} catch (InterruptedException e) {}
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {}
				System.out.println(phone.getBrand()+"---"+phone.getPrice());
				phone.setStore(false);
				phone.notify();
			}
		}
	}
}

多个生产者多个消费者

public class Test01 {

	public static void main(String[] args) {
		
		Phone phone = new Phone();
		Producer producer1 = new Producer(phone);
		Producer producer2 = new Producer(phone);
		Consumer consumer1 = new Consumer(phone);
		Consumer consumer2 = new Consumer(phone);
		
		producer1.start();
		producer2.start();
		consumer1.start();
		consumer2.start();
		
	}
}

//手机类
public class Phone {
	private String brand;
	private double price;
	private boolean store;
	
	public Phone() {

	}
	public Phone(String brand, int price) {
		this.brand = brand;
		this.price = price;
	}

	public String getBrand() {
		return brand;}
	public void setBrand(String brand) {
		this.brand = brand;
	}
	
	public double getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	
	public boolean isStore() {
		return store;
	}
	public void setStore(boolean store) {
		this.store = store;
	}
}

//生产者
public class Producer extends Thread{
	private Phone phone;
	public Producer(Phone phone) {
		this.phone = phone;
	}
	@Override
	public void run() {
		boolean flag=true;
		while(true) {
			synchronized (phone) {
				while(phone.isStore()==true) {
					try {
						phone.wait();
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
				}
				if(flag) {
					phone.setBrand("三星");
					phone.setPrice(4999);
				}else {
					phone.setBrand("小米");
					phone.setPrice(1999);
				}
				flag=!flag;
				phone.setStore(true);
				phone.notifyAll();
			}
		}
	}
}

//消费者
public class Consumer extends Thread{
	private Phone phone;
	public Consumer(Phone phone) {
		this.phone = phone;
	}
	@Override
	public void run() {
		while(true) {
			synchronized (phone) {
				while(phone.isStore()==false) {
					try {
						phone.wait();
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				System.out.println(phone.getBrand()+"---"+phone.getPrice());
				phone.setStore(false);
				phone.notifyAll();
			}
			
		}
	}
}
  1. 案例二:

实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓储,生产者消费者模型就显得没有说服力了。
对于此模型,应该明确一下几点:
1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费

生产者消费者仓储模式

public class Test01 {

	public static void main(String[] args) {
		//生产者-仓储-消费者
		Store store = new Store();
		Producer producer = new Producer(store);
		Consumer consumer = new Consumer(store);
		
		producer.start();
		consumer.start();	
	}
}

//仓储
public class Store {

	private int max = 20;//最大容量
	private int num = 0;//最小容量
	//入库
	public void push() {
		synchronized (this) {
			if(num>=max) {
				try {
					this.wait();
				} catch (InterruptedException e) {
				}
			}
			num++;
			System.out.println("入库"+num);
			this.notify();
		}
	}



	//出库
	public void pop() {
		synchronized (this) {
			if(num<=0) {
				try {
					this.wait();
				} catch (InterruptedException e) {
				}
			}
			num--;
			System.out.println("出库:"+num);
			this.notify();
		}
	}



}


//生产者
public class Producer extends Thread{
	private Store store;

	public Producer(Store store) {
		this.store=store;
	}
	@Override
	public void run() {
		while(true) {
			store.push();
		}
	}

}

//消费者
public class Consumer extends Thread{
	private Store store;

	public Consumer(Store store) {
		this.store = store;
	}
	@Override
	public void run() {
		while(true) {
			store.pop();
		}
	}
}

卖包子模型-LinkedList先进先出

public class Test01 {

	public static void main(String[] args) {
		
		Store store = new Store();
		Producer producer1 = new Producer(store);
		Producer producer2 = new Producer(store);
		Producer producer3 = new Producer(store);
		Consumer consumer1 = new Consumer(store);
		Consumer consumer2 = new Consumer(store);
		Consumer consumer3 = new Consumer(store);
		Consumer consumer4 = new Consumer(store);
		Consumer consumer5 = new Consumer(store);
		Consumer consumer6 = new Consumer(store);
		
		producer1.start();
		producer2.start();
		producer3.start();
		consumer1.start();
		consumer2.start();
		consumer3.start();
		consumer4.start();
		consumer5.start();
		consumer6.start();
		
	}
}

包子类
public class BaoZi {
	private String time;
	public BaoZi() {}
	public BaoZi(String time) {
		this.time = time;
	}
	/**
	 * @return time
	 */
	public String getTime() {
		return time;
	}
	/**
	 * @param time 要设置的 time
	 */
	public void setTime(String time) {
		this.time = time;
	}
	/* (非 Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "包子日期" + time;
	}
	
}

仓储
public class Store {

	private int max = 20;//最大容量
	private int num = 0;//最小容量
	private LinkedList<BaoZi>  list = new LinkedList<>();
	//入库
	public void push() {
		synchronized (this) {
			while(num>=max) {
				try {
					this.wait();
				} catch (InterruptedException e) {
				}
			}
			num++;
			System.out.println("入库"+num);
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
			String time = sdf.format(new Date());
			BaoZi baoZi = new BaoZi(time);
			list.add(baoZi);
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			this.notifyAll();
		}
	}



	//出库
	public void pop() {
		synchronized (this) {
			while(num<=0) {
				try {
					this.wait();
				} catch (InterruptedException e) {
				}
			}
			num--;
			System.out.println("出库:"+num+list.removeFirst());
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			this.notifyAll();
		}
	}



}

生产者
public class Producer extends Thread{
	private Store store;

	public Producer(Store store) {
		this.store=store;
	}
	@Override
	public void run() {
		while(true) {
			store.push();
		}
	}

}

消费者
public class Consumer extends Thread{
	private Store store;

	public Consumer(Store store) {
		this.store = store;
	}
	@Override
	public void run() {
		while(true) {
			store.pop();
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值