JAVA - 多线程 - 生产者与消费者

生产者消费者模型

  1. 生产者线程:能够生产两种产品(中文、英文),生产者产出信息后将其放到一个区域之中;
  2. 消费者线程:不停的从区域中取走生产者生产出来的产品;
  3. 产品的生产是需要耗费一定时间的。

基本实现

  • 定义一个产品类Product,作为产品存放区;
  • 定义Productor线程,生产产品;
  • 定义Consumer线程,取走产品。
//产品
class Product {
	private String name = "苹果";
	private String content = "爱疯";
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}	
}
//生产者线程
class Productor implements Runnable {
	private Product product = null;
	public Productor(Product product){
		this.product = product;
	}
	public void run() {
		boolean flag = true;    //控制生产哪种产品
		for(int i = 0; i < 50; i++) {
			if(flag) {     //如果flag是TRUE,生产第一种产品
				this.product.setName("苹果");
				try {                   //线程休眠,模拟生产需要时间
					Thread.sleep(90);
				} catch (Exception e) {
					e.printStackTrace();
				}
				this.product.setContent("爱疯");
				flag = false;
			} else {
				this.product.setName("Apple");
				try {
					Thread.sleep(90);
				} catch (Exception e) {
					e.printStackTrace();
				}
				this.product.setContent("Iphone");
				flag = true;
			}
		}		
	}	
}
//消费者线程
class Consumer implements Runnable {
	private Product product = null;
	public Consumer(Product product) {
		this.product = product;
	}
	public void run() {
		for(int i = 0; i < 50; i++) {
			try {
				Thread.sleep(100);
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println(this.product.getName() + " ----> " + this.product.getContent()); //取走产品
		}
	}	
}
//MAIN函数
public class ProductorConsumerDemo {
	public static void main(String[] args) {
		Product product = new Product(); //产品存放区
		Productor productor = new Productor(product);
		Consumer consumer = new Consumer(product);
		new Thread(productor).start(); //启动生产者线程,生产产品
		new Thread(consumer).start();  //启动消费者线程,取走产品
	}
}

 

运行结果:

Apple ----> 爱疯
苹果 ----> Iphone
Apple ----> 爱疯
苹果 ----> 爱疯
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone


存在的问题

  1. 中文产品与英文产品的信息混在一起:原因是因为生产需要一定的时间,当生产者线程中一种产品还没生产完就切换到消费者线程,解决方案是生产者线程在生产的时候需要加入同步操作;
  2. 生产者生产了若干个产品,消费者才开始取走产品:原因是生产者线程在休眠的时候,消费者线程重复取走产品,解决方案是加入等待唤醒机制。

 

问题的解决

  1. 将Product类生产和读取封装成不同的方法,并将其设置为同步方法;
  2. 在生产和消费方法中加入等待唤醒机制,生产方法需要等待消费方法取走产品后的通知才能继续生产,消费方法需要等待生产方法生产完成通知后才能继续取走。

代码实现:

 

//产品
class Product {
	private String name = "苹果";
	private String content = "爱疯";
	private boolean flag = false; //是否可取走产品的标志位,TRUE可取走,FALSE可生产
	//封装生产方法
	public synchronized void set(String name, String content) { //同步方法解决问题一
		if(!flag) {
			try {
				super.wait();   //生产者线程等待,线程等待唤醒解决问题二
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		this.setName(name);
		try {
			Thread.sleep(300);
		} catch (Exception e) {
			e.printStackTrace();
		}
		this.setContent(content);
		flag = false;
		super.notify(); //唤醒消费者线程
	}
	
	//封装消费方法
	public synchronized void get() {
		if(flag) {
			try {
				super.wait();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		try {
			Thread.sleep(300);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(this.getName() + " ----> " + this.getContent()); //取走产品
		flag = true;
		super.notify();
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}	
}
//生产者线程
class Productor implements Runnable {
	private Product product = null;
	public Productor(Product product){
		this.product = product;
	}
	public void run() {
		boolean flag = true;    //控制生产哪种产品
		for(int i = 0; i < 50; i++) {
			if(flag) {     //如果flag是TRUE,生产第一种产品
				this.product.set("苹果", "爱疯");
				flag = false;
			} else {
				this.product.set("Apple", "Iphone");
				flag = true;
			}
		}		
	}	
}
//消费者线程
class Consumer implements Runnable {
	private Product product = null;
	public Consumer(Product product) {
		this.product = product;
	}
	public void run() {
		for(int i = 0; i < 50; i++) {
			try {
				Thread.sleep(100);
			} catch (Exception e) {
				e.printStackTrace();
			}
			this.product.get();
		}
	}	
}
//MAIN函数
public class ProductorConsumerDemo {
	public static void main(String[] args) {
		Product product = new Product(); //产品存放区
		Productor productor = new Productor(product);
		Consumer consumer = new Consumer(product);
		new Thread(productor).start(); //启动生产者线程,生产产品
		new Thread(consumer).start();  //启动消费者线程,取走产品
	}
}


BR~

Jianwei Wang

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值