Java併發編程七 生產者消費者模式

Java併發編程七 生產者消費者模式

生產者-消費者模式是一個經典的多線程設計模式,它爲多線程的協作提供了良好的解決方案。在生產者-消費者模式中,通常有兩類線程,即若干個生產者線程和若干個消費者線程。生產者線程負責提交用戶請求,消費者線程負責處理用戶請求。生產者和消費者之間通過共享內存緩衝區進行通信。
生產者-消費者模式中的內存緩衝區的主要功能是數據在多線程間的共享。此外,通過該緩衝區,可以緩解生產者和消費者之間的性能差。
生產者消費者模式

阻塞隊列實現

舉一個雞下蛋供人吃的例子:

/**
 * 雞蛋
 * Created by lyyz on 18-5-15.
 */
public class Egg {
    private String id;

    public Egg(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
/**
 * 生產者 雞下蛋裝入籃子
 * Created by lyyz on 18-5-15.
 */
public class Chicken implements Runnable {
    private String name;
    private BlockingQueue<Egg> queue;
    private AtomicInteger count = new AtomicInteger();
    private volatile boolean isRunning = true;
    public Chicken(String name, BlockingQueue<Egg> queue) {
        this.name = name;
        this.queue = queue;
    }

    @Override
    public void run() {
        while(isRunning){
            try {
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            count.incrementAndGet();
            Egg egg = new Egg("雞-"+name+"-"+count.get());
            queue.add(egg);
            System.out.println("雞-"+name+"下了第"+count.get()+"個蛋 放入籃子中");
        }
    }

    public void stop(){
        isRunning = false;
    }
}

/**
 * 消費者 人吃籃子中的雞蛋
 * Created by lyyz on 18-5-15.
 */
public class People implements Runnable {
    private String name;
    private BlockingQueue<Egg> queue;
    private AtomicInteger count = new AtomicInteger();
    private volatile boolean isRunning = true;
    public People(String name, BlockingQueue<Egg> queue) {
        this.name = name;
        this.queue = queue;
    }

    @Override
    public void run() {
        while(isRunning){
            try {
                Thread.sleep(new Random().nextInt(1000));
                count.incrementAndGet();
                Egg egg = queue.take();
                System.out.println("人-"+name+"吃了 "+egg.getId()+"這是吃的第"+count.get()+"個蛋了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void stop(){
        isRunning = false;
    }
}
/**
 * 雞下蛋供人吃的例子
 * Created by lyyz on 18-5-15.
 */
public class Main {
    public static void main(String[] args) {
        //阻塞的有界隊列 裝雞蛋的籃子
        BlockingQueue<Egg> queue = new ArrayBlockingQueue<Egg>(10);
        //創建4只雞
        Chicken chicken1 = new Chicken("小紅",queue);
        Chicken chicken2 = new Chicken("小黃",queue);
        Chicken chicken3 = new Chicken("小黑",queue);
        Chicken chicken4 = new Chicken("小綠",queue);
        //創建三個人
        People people1 = new People("劉備",queue);
        People people2 = new People("張飛",queue);
        People people3 = new People("關羽",queue);
        //線程池
        ExecutorService es = Executors.newCachedThreadPool();
        es.execute(chicken1);
        es.execute(chicken2);
        es.execute(chicken3);
        es.execute(chicken4);
        es.execute(people1);
        es.execute(people2);
        es.execute(people3);

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        chicken1.stop();
        chicken2.stop();
        chicken3.stop();
        chicken4.stop();
        while(!queue.isEmpty()){

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        people1.stop();
        people2.stop();
        people3.stop();
        es.shutdown();
        System.out.println("--------------------end------------------------");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章