關於java中生產者消費者模式的理解


   在說生產者消費者模式之前,我覺得有必要理解一下 Obj.wait(),與Obj.notify()方法。wait()方法是指在持有對象鎖的線程調用此方法時,會釋放對象鎖,同時休眠本線程。notify()方法是持有相同的對象鎖來喚醒休眠的線程,使其具有搶占cpu的資格。可以理解同步方法,同步方法的對象鎖就是誰調用這個方法,這個對象就是對象鎖。

        根據李興華老師的視頻講解,建立一個生產者類,一個消費者類,還有一個Info類,貼上代碼:

1.生產者類

package com.company;

/**
 * Created by Administrator on 2016/8/30.
 */
public class Productor implements Runnable {

    private Info info;

    public Productor(Info info) {
        this.info = info;
    }

    @Override
    public void run() {

        for (int i=0;i<50;i++)
        {
            if (i%2==0)
            {
//                info.setTitle("陶帥");
//                info.setContent("一個帥哥");
//                try {
//                    Thread.sleep(100);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                info.set("陶帥","一個帥哥");
            }else {
//                info.setTitle("可愛的動物");
//                info.setContent("草泥馬");
                info.set("可愛的動物","草泥馬");
//                try {
//                    Thread.sleep(100);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
            }
        }
    }
}

2.消費者類

package com.company;

/**
 * Created by Administrator on 2016/8/30.
 */
public class Consumer implements Runnable {
    private Info info;

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

    @Override
    public void run() {

        for (int i=0;i<50;i++)
        {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           info.get();
        }
    }
}

3.Info類(重點)

package com.company;

/**
 * Created by Administrator on 2016/8/30.
 */
public class Info {
    private String Title;
    private String content;
    private boolean flag=true;//true表示可以生產不能取走消費,false相反


    public synchronized void set(String Titile,String content){
        if (!flag)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.Title=Titile;
        this.content=content;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        flag=false;
        notify();
    }

    public synchronized void get(){
        if (flag)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(this.Title+"------->"+this.content);
        flag=true;
        notify();
    }


//    public String getTitle() {
//        return Title;
//    }
//
//    public void setTitle(String title) {
//        Title = title;
//    }
//
//    public String getContent() {
//        return content;
//    }
//
//    public void setContent(String content) {
//        this.content = content;
//    }
}

4.測試類

package com.company;

public class Main {

    public static void main(String[] args) {
    Info info=new Info();
        Productor p=new Productor(info);
        Consumer c=new Consumer(info);
        new Thread(p).start();
        new Thread(c).start();
    }
}

總結分析:生產者和消費者兩個線程同時搶占CPU,假如消費者先搶到,此時調用get()方法即消費取走,但是此時flag為true,因此會進入wait()方法,所以此時只能是生產者搶占到CPU,根據生產者調用set()方法,生產后執行

        flag=false;
        notify();

此時生產者和消費者所在的兩個線程又站在同一起跑線上了,繼續CPU爭奪戰。如果不幸的消費者又沒有搶過生產者,生產者繼續執行set();此時flag已經是false了,根據代碼

 if (!flag)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

所以生產者只能乖乖的wait();CPU回到消費者這里,循環往復,模式就出來了,完美!



 


免責聲明!

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



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