多線程(生產者和消費者模式)


多線程的理解分析:

生產者和消費者多線程體現(線程間通信問題)以學生作為資源來實現的
        生產者Producer 生產某個對象(共享資源),放在緩沖池中,然后消費者從緩沖池中取出這個對象。也就是生產者生產一個,消費者取出一個。這樣進行循環
        資源類:Student
        設置數據類:SetThread(生產者)
        獲取數據類:GetThread(消費者)
        測試類:StudentDemo
        

1. 資源類 Student

package FF;

public class Student {
    private String name;
    private int age;
    private boolean flag; // 默認情況是沒有數據,如果是true,說明有數據

    public synchronized void set(String name, int age) {
        // 如果有數據,就等待
        if (this.flag) {
            try {
                this.wait();//等待,釋放鎖
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 設置數據
        this.name = name;
        this.age = age;

        // 修改標記
        this.flag = true;
        this.notify();
    }

    public synchronized void get() {
        // 如果沒有數據,就等待
        if (!this.flag) {
            try {
                this.wait();//等待,釋放鎖
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 獲取數據
        System.out.println(this.name + "---" + this.age);

        // 修改標記
        this.flag = false;
        this.notify();
    }
}

 

2. 設置數據類:SetThread(生產者)


  

package FF;

public class SetThread implements Runnable {

    private Student s;
    private int x = 0;

    public SetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            if (x % 2 == 0) {
                s.set("林青霞", 27);
            } else {
                s.set("劉意", 30);
            }
            x++;
        }
    }
}

 

3.GetThread(消費者)

package FF;

public class GetThread implements Runnable {
    private Student s;

    public GetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            s.get();
        }
    }
}

 

 

4.測試類:StudentDemo

package FF;

/*
 * 分析:
 *         資源類:Student    
 *         設置學生數據:SetThread(生產者)
 *         獲取學生數據:GetThread(消費者)
 *         測試類:StudentDemo
 * 
 * 問題1:按照思路寫代碼,發現數據每次都是:null---0
 * 原因:我們在每個線程中都創建了新的資源,而我們要求的時候設置和獲取線程的資源應該是同一個
 * 如何實現呢?
 *         在外界把這個數據創建出來,通過構造方法傳遞給其他的類。
 * 
 * 問題2:為了數據的效果好一些,我加入了循環和判斷,給出不同的值,這個時候產生了新的問題
 *         A:同一個數據出現多次
 *         B:姓名和年齡不匹配
 * 原因:
 *         A:同一個數據出現多次
 *             CPU的一點點時間片的執行權,就足夠你執行很多次。
 *         B:姓名和年齡不匹配
 *             線程運行的隨機性
 * 線程安全問題:
 *         A:是否是多線程環境        是
 *         B:是否有共享數據        是
 *         C:是否有多條語句操作共享數據    是
 * 解決方案:
 *         加鎖。
 *         注意:
 *             A:不同種類的線程都要加鎖。
 *             B:不同種類的線程加的鎖必須是同一把。
 * 
 * 問題3:雖然數據安全了,但是呢,一次一大片不好看,我就想依次的一次一個輸出。
 * 如何實現呢?
 *         通過Java提供的等待喚醒機制解決。
 * 
 * 等待喚醒:
 *         Object類中提供了三個方法:
 *             wait():等待,釋放鎖
 *             notify():喚醒單個線程
 *             notifyAll():喚醒所有線程
 *         為什么這些方法不定義在Thread類中呢?
 *             這些方法的調用必須通過鎖對象調用,而我們剛才使用的鎖對象是任意鎖對象。
 *             所以,這些方法必須定義在Object類中。
 * 
 * 最終版代碼中:
 *         把Student的成員變量給私有的了。
 *         把設置和獲取的操作給封裝成了功能,並加了同步。
 *         設置或者獲取的線程里面只需要調用方法即可。
 */
public class StudentDemo {
    public static void main(String[] args) {
        //創建資源
        Student s = new Student();
        
        //設置和獲取的類
        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        //線程類
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        //啟動線程
        t1.start();
        t2.start();
    }
}

 

 

 

 

 

 


         

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM