生产者消费者模型
- 生产者线程:能够生产两种产品(中文、英文),生产者产出信息后将其放到一个区域之中;
- 消费者线程:不停的从区域中取走生产者生产出来的产品;
- 产品的生产是需要耗费一定时间的。
基本实现
- 定义一个产品类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
存在的问题
- 中文产品与英文产品的信息混在一起:原因是因为生产需要一定的时间,当生产者线程中一种产品还没生产完就切换到消费者线程,解决方案是生产者线程在生产的时候需要加入同步操作;
- 生产者生产了若干个产品,消费者才开始取走产品:原因是生产者线程在休眠的时候,消费者线程重复取走产品,解决方案是加入等待唤醒机制。
问题的解决
- 将Product类生产和读取封装成不同的方法,并将其设置为同步方法;
- 在生产和消费方法中加入等待唤醒机制,生产方法需要等待消费方法取走产品后的通知才能继续生产,消费方法需要等待生产方法生产完成通知后才能继续取走。
代码实现:
//产品
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