一、定義
Producer-Consumer Pattern就是生產(chǎn)者-消費者模式聪姿。
生產(chǎn)者和消費者在為不同的處理線程咳燕,生產(chǎn)者必須將數(shù)據(jù)安全地交給消費者,消費者進(jìn)行消費時招盲,如果生產(chǎn)者還沒有建立數(shù)據(jù)曹货,則消費者需要等待。
一般來說玩般,可能存在多個生產(chǎn)者和消費者礼饱,不過也有可能生產(chǎn)者和消費者都只有一個,當(dāng)雙方都只有一個時匀伏,我們也稱之為Pipe Pattern蝴韭。
二榄鉴、模式案例
該案例中蛉抓,定義了3個角色:廚師、客人剃诅、桌子巷送。
廚師(生產(chǎn)者)定義:
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++;
}
}
客人(消費者)定義:
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;
}
}
執(zhí)行:
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();
}
}
三、模式講解
Producer-Consumer模式的角色如下:
- Data(數(shù)據(jù))參與者
Data代表了實際生產(chǎn)或消費的數(shù)據(jù)综苔。 - Producer(生產(chǎn)者)參與者
Producer會創(chuàng)建Data惩系,然后傳遞給Channel參與者。 - Consumer(消費者)參與者
Consumer從Channel參與者獲取Data數(shù)據(jù)如筛,進(jìn)行處理堡牡。 - Channel(通道)參與者
Channel從Producer參與者處接受Data參與者,并保管起來杨刨,并應(yīng)Consumer參與者的要求晤柄,將Data參與者傳送出去。為確保安全性芥颈,Producer參與者與Consumer參與者要對訪問共享互斥。