您的位置:首页 > 编程语言 > Java开发

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

2015-10-19 19:12 429 查看

生产者消费者模型

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

基本实现

定义一个产品类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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息