延續昨天介紹 Exchanger 的部份,Exchanger 玊要可以將二個 Thread 的資料做交換。在寫Producer Consumer 程式的使用情境,適合使用 Exchanger 這個 Class。Producer 用來產生資料而 Consumer 就是用來消費 Producer 所生產的資料。
以下來撰寫一個 Sample Code, 透過使用 Exchanger Class 來實作 Producer Consumer 的程式:
import java.util.concurrent.Exchanger;
public class ProducerThreadExample implements Runnable {
private Exchanger<StringBuffer> exchanger;
private StringBuffer sb = new StringBuffer();
public ProducerThreadExample(Exchanger<StringBuffer> exchanger) {
this.exchanger = exchanger;
}
@Override
public void run() {
try {
for (int i = 1 ; i <= 10 ; i++) {
sb.append("message-");
sb.append(i);
sb = this.exchanger.exchange(sb);
}
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
上面的程式是 Producer Thread 的程式,主要用來產生 message 字串的訊息,然後放入到 StringBuffer 物件裡,之後會和 Consumer 去做資料的交換,程式如下:
import java.util.concurrent.Exchanger;
public class ConsumerThreadExample implements Runnable {
private Exchanger<StringBuffer> exchanger;
public ConsumerThreadExample(Exchanger<StringBuffer> exchanger) {
this.exchanger = exchanger;
}
@Override
public void run() {
try {
for (int i = 1 ; i <= 10 ; i++) {
StringBuffer sb = new StringBuffer();
sb = this.exchanger.exchange(sb);
System.out.println("Consumer:" + sb.toString());
}
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
Consumer Thread 的程式用來和 Producer Thread 交換訊息,Consumer 會傳給 Producer Thread 一個空的 StringBuffer 然後 Producer Thread 會去 append 資料。之後 Consumer Thread 會將交換來的訊息印到 Console 上。主程式啟動 Thread 的程式如下:
import java.util.concurrent.Exchanger;
public class Test {
public static void main(String args[]) {
Exchanger<StringBuffer> exchanger = new Exchanger<StringBuffer>();
ProducerThreadExample p = new ProducerThreadExample(exchanger);
Thread producerThread = new Thread(p);
ConsumerThreadExample c = new ConsumerThreadExample(exchanger);
Thread consumerThread = new Thread(c);
producerThread.start();
consumerThread.start();
}
}
主程式就會用來啟動 Producer Thread 以及 Consumer Thread,執行的結果如下:
Consumer:message-1
Consumer:message-2
Consumer:message-3
Consumer:message-4
Consumer:message-5
Consumer:message-6
Consumer:message-7
Consumer:message-8
Consumer:message-9
Consumer:message-10
使用 Exchanger 寫 Producer Consumer 會有缺點,就是當 Producer Thread產生完資料之後如果呼叫 Exchanger 時就會被阻塞住,要等到 Consumer 也呼叫 Exchanger 才會繼續的往下生產資料執行。因此如果要做 Producer Consumer 的程式,在 Producer 和 Consumer 之間最好要放一個 Queue,這樣 Producer 就可以不管 Consumer 是否有被執行就可以一直生產資料,這樣才有辦法去解 Producer Consumer 程式的耦合,但是要控制好 Queue 不然會有爆掉的機會。