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

来源:互联网 发布:windows xp 美化大师 编辑:程序博客网 时间:2024/05/23 02:15

生产者消费者模型(多个生产者和多个消费者)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来更高效解决这个问题。

0 0
原创粉丝点击