Java多線程基礎(七)——Producer-Consumer模式

1、定義

Producer-Consumer Pattern就是生產者-消費者模式。
生產者和消費者在爲不一樣的處理線程,生產者必須將數據安全地交給消費者,消費者進行消費時,若是生產者尚未創建數據,則消費者須要等待。
通常來講,可能存在多個生產者和消費者,不過也有可能生產者和消費者都只有一個,當雙方都只有一個時,咱們也稱之爲Pipe Pattern安全

2、模式案例

該案例中,定義了3個角色:廚師、客人、桌子。dom

廚師(生產者)定義:this

public class MakerThread extends Thread {
    private final Random random;
    private final Table table;
    private static int id = 0;     //蛋糕的流水號(全部廚師共通)
    public MakerThread(String name, Table table, long seed) {
        super(name);
        this.table = table;
        this.random = new Random(seed);
    }
    public void run() {
        try {
            while (true) {
                Thread.sleep(random.nextInt(1000));
                String cake = "[ Cake No." + nextId() + " by " + getName() + " ]";
                table.put(cake);
            }
        } catch (InterruptedException e) {
        }
    }
    private static synchronized int nextId() {
        return id++;
    }
}

客人(消費者)定義:spa

public class EaterThread extends Thread {
    private final Random random;
    private final Table table;
    public EaterThread(String name, Table table, long seed) {
        super(name);
        this.table = table;
        this.random = new Random(seed);
    }
    public void run() {
        try {
            while (true) {
                String cake = table.take();
                Thread.sleep(random.nextInt(1000));
            }
        } catch (InterruptedException e) {
        }
    }
}

桌子(隊列)定義:線程

public class Table {
    private final String[] buffer;
    private int tail;
    private int head;
    private int count;
 
    public Table(int count) {
        this.buffer = new String[count];
        this.head = 0;
        this.tail = 0;
        this.count = 0;
    }
    public synchronized void put(String cake) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " puts " + cake);
        while (count >= buffer.length) {
            wait();
        }
        buffer[tail] = cake;
        tail = (tail + 1) % buffer.length;
        count++;
        notifyAll();
    }
    public synchronized String take() throws InterruptedException {
        while (count <= 0) {
            wait();
        }
        String cake = buffer[head];
        head = (head + 1) % buffer.length;
        count--;
        notifyAll();
        System.out.println(Thread.currentThread().getName() + " takes " + cake);
        return cake;
    }
}

執行:code

public class Main {
    public static void main(String[] args) {
        Table table = new Table(3);
        new MakerThread("MakerThread-1", table, 31415).start();
        new MakerThread("MakerThread-2", table, 92653).start();
        new MakerThread("MakerThread-3", table, 58979).start();
        new EaterThread("EaterThread-1", table, 32384).start();
        new EaterThread("EaterThread-2", table, 62643).start();
        new EaterThread("EaterThread-3", table, 38327).start();
    }
}

3、模式講解

Producer-Consumer模式的角色以下:blog

  • Data(數據)參與者

Data表明了實際生產或消費的數據。隊列

  • Producer(生產者)參與者

Producer會建立Data,而後傳遞給Channel參與者。ip

  • Consumer(消費者)參與者

Consumer從Channel參與者獲取Data數據,進行處理。rem

  • Channel(通道)參與者

Channel從Producer參與者處接受Data參與者,並保管起來,並應Consumer參與者的要求,將Data參與者傳送出去。爲確保安全性,Producer參與者與Consumer參與者要對訪問共享互斥。

相關文章
相關標籤/搜索