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

生产者消费者模型(多个生产者和多个消费者)JDK1.5之前实现版

2016-04-08 09:58 519 查看

生产者消费者模型(多个生产者和多个消费者)JDK1.5之前实现版

场景描述

多线程开发中很经典的一个案例就是生产者消费者模型,它们共享资源,但是对资源的操作方式并不同。因此它们需要协调资源,否则就会出现线程安全问题。尤其当时多个生产者和多个消费者时比较麻烦。本文以JDK1.5之前synchronized关键字和等待唤醒机制实现多生产者多消费者模型。

代码展示

Resource Code

/**
* 生产者和消费者共享的资源Resource对象
* @author xuyi3
* @2016年4月7日 @下午2:01:21
* @Resource
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class Resource {

/** 资源名称 */
private String name;
/** 资源标识符 */
private boolean flag = false;
// 区分产品的计数器
private int count = 0;

/**
* 生产产品方法
* @param threadName
*/
public synchronized void produce(String threadName) {
while (isFlag()) {// 如果已经存在数据,生产者就等待消费者消费之后再生产。注意多生产者时这里要使用while循环判断。
// wait()
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
setName("产品" + (++count));
System.out.println(threadName + "生产者生产--->" + getName());
setFlag(true);
// 唤醒所有线程
// 这是jdk1.5之前的解决方案,这里正在的意图其实是唤醒消费者所有线程,而不是把生产者和消费者都唤醒。
this.notifyAll();
}

/**
* 消费产品方法
* @param threadName
*/
public synchronized void consumer(String threadName) {

while (!isFlag()) {// 如果没有数据消费者就等待生产者生产之后再消费,多消费者时这里要使用while循环判断。
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(threadName + "消费者消费=====》" + getName());
setFlag(false);// 标识已经消费了
// 唤醒所有线程
// 这是jdk1.5之前的解决方案,这里正在的意图其实是唤醒生产者所有线程,而不是把消费者和生产者都唤醒。
this.notifyAll();
}
}


ProductThread Code

/**
* 生产者线程
* @author xuyi3
* @2016年4月7日 @下午1:38:16
* @ProductThread
* @功能说明:生产产品<br>
* @春风十里不如你
* @备注
*/
public class ProductThread implements Runnable {
// 共享资源对象
private Resource resource;
public ProductThread(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
// 备注:比较优雅的多线程代码,在run()方法体内尽量出现较少的代码,不推荐把同步代码和一些复杂的逻辑放在run()方法体内。
// 因为如果把所有同步代码都放在run()方法体内写的话,非常不好的维护并且代码结构不够清晰。
while (true) {
// 生产者生产产品
resource.produce(Thread.currentThread().getName());
}

}
}


ConsumerThread Code

/**
* 消费者对象
* @author xuyi3
* @2016年4月7日 @下午2:07:22
* @ConsumerThread
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class ConsumerThread implements Runnable {
// 共享资源Resource对象
private Resource resource;
public ConsumerThread(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
// 备注:比较优雅的多线程代码,在run()方法体内尽量出现较少的代码,不推荐把同步代码和一些复杂的逻辑放在run()方法体内。
// 因为如果把所有同步代码都放在run()方法体内写的话,非常不好的维护并且代码结构不够清晰。
while (true) {
// 消费者消费产品
resource.consumer(Thread.currentThread().getName());
}
}
}


AppMain Code

public class AppMain {
public static void main(String[] args) {
// 共享资源对象
Resource resource = new Resource();
// 创建生产者对象
ProductThread productThread = new ProductThread(resource);
// 创建消费者对象
ConsumerThread consumerThread = new ConsumerThread(resource);

// 启动两个线程
new Thread(productThread, "生产者1 ").start();
new Thread(consumerThread, "Consumer1").start();
new Thread(productThread, "生产者2 ").start();
new Thread(consumerThread, "Consumer2").start();
}
}


总结说明

多个生产者和多个消费者模型实现的关键在于,资源共享(同步同个对象锁)和资源的标识以及等待唤醒机制wait()和notifyAll()方法。但是每次都需要要判断标识符,因此需要使用while而不能试if。JDK1.5之前使用这种方式处理还不错,但是这里有个明显的问题就是,每次都是唤醒所有的线程,并不是只唤醒我们希望唤醒的线程。这是会降低效率的,尤其是在线程数比较多并发量比较高的时候,就会显得性能并不高。下一章使用JDK1.5之后的并发包下的Lock和Condition来更高效解决这个问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息