使用Object类中的wait()和notify()方法实现生产者和消费者模式

      生产者消费者模式,在实际的开发过程中经常会遇到,平常我们接触到的例如ActiveMQ就是一个一个典型的生产者消费者模式。为了更好的理解生产者和消费这模式,下面通过自己定义的一个消息类、结合Object对象中的wait()和notify()方法实现一个简单的生产者消费者模式。

  首先定义一个消息类Info.

package com.test.consumer;

/**
 * @生产消息类
 */
public class Info {
    /** 消息的标题 */
    private String title;
    /** 消息的内容 */
    private String content;
    /**
     * 消息的标识, 当flag=false的时候,生产者只能生产消息,消费者不能消费消息
     * 当flag=true的时候,消费者只能消费消息,生产者不能生产消息
     * */
    private boolean flag;

    /**
     * 设置消息的内容
     */
    public synchronized void set(String title, String content) {
        if (flag == true) {
            try {
                super.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        this.title = title;
        this.content = content;
        super.notify();
        this.flag = true;
    }

    /**
     * 获取消息内容
     */
    public synchronized void get() {
        if (flag == false) {
            try {
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("标题:" + this.title + ",内容:" + this.content);
        super.notify();
        this.flag = false;
    }

}
 接着定义一个生产消息的类,默认实现Runnable接口,这样可以在多线程的环境下进行测试。

 

package com.test.consumer;
 /**
 *生产者类
 */
public class Producer implements Runnable {
    /**定义一个自己的消息类,通过构造器注入*/
    private Info info;

    public Producer(Info info) {
        super();
        this.info = info;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                info.set("java", "java基础");
            } else {
                info.set("spring", "跟我学springMVC");
            }
        }

    }

}
接着创建一个消费者类,同样的实现Runnable接口

package com.test.consumer;

/**
 * 消费者
 */
public class Consumer implements Runnable {
    /** 定义一个自己的消息类,通过构造器注入获取消息 */
    private Info info;

    public Consumer(Info info) {
        super();
        this.info = info;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            this.info.get();
        }

    }

}
创建测试类,测试。

package com.test.consumer;

public class TestDemo {

    public static void main(String[] args) {
       Info info = new Info();//定义一个公共的消息类
       new Thread(new Producer(info)).start();//生产者开始生产消息
       new Thread(new Consumer(info)).start();//消费者开始消费消息
    }

}
运行结果:

标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC
标题:java,内容:java基础
标题:spring,内容:跟我学springMVC

   从上面的运行结果可以看出来,生产者先生产消息,然后消费者取出消息后,输出,观察后发现运行结果没有错位,即实现生产一个消息取出来一个消息。

  这里对info消息类中的set和get方法上添加了synchronized同步关键字,作用是在多线程的环境下能够同步的生产存取, 属性flag相当于一个信号灯,true和false,代表数据的两种状态,在flag为true的情况下,只能生产消息,不能消费消息,消息生产完成后,将flag置为false,表示消费者可以消费消息,同时通过notify()方法唤醒,正在等待的消费线程,开始消费消息;这个时候只能消费消息,wait()方法阻塞生产者线程,等待消费者消费完成后消费者使用notify()方法唤醒正在等待的生产者线程开始生产消息,同时flag置为true,这个是消费者再次消费消息的时候,遇到falg=true,则进入等待阻塞状态,这样一次的生产、一次消费;一次生产,一次消费。

发布了25 篇原创文章 · 获赞 9 · 访问量 13万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章