使用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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章