應用場景?
這個模式,我在做服務器的時候沒有遇到過,但是應用場景很簡單,當上下調用的時候出現很大的性能差異的時候,可以使用這個模式解決,性能差的那方多放幾放幾個線程,中間用一個隊列連接2方的信息傳輸與緩衝,這樣聽起來是不是感覺科學計算中是不是很有應用場景呢?
角色模擬
- PCData:模擬消息
- Producter:生產者,創建消息的類,不斷的創建消息到管道中
- Consumer:消費者,不斷的重管道中提取消息,並處理
- Main:創建生成者和消費者,並利用線程池運行他們,打印他們的運行過程
代碼
- PCData消息類
public final class PCData {
private final int intData;
public PCData(int d){
intData=d;
}
public PCData(String d){
intData=Integer.valueOf(d);
}
public int getData(){
return intData;
}
@Override
public String toString(){
return "data:"+intData;
}
}
- Producter生產者,這裏需要注意的是volatile 關鍵字、併發類BlockingQueue的用法
public class Producter implements Runnable {
private volatile boolean isRuning = true;//volatile是爲了保證isRuning在多線程數據共享一致性
private BlockingQueue<PCData> queue;
private static AtomicInteger count = new AtomicInteger();//原子操作類
private static final int SLEEPTIME = 1000;
public Producter(BlockingQueue<PCData> queue){
this.queue = queue;
}
@Override
public void run() {
PCData data = null;
Random r = new Random();
System.out.println("start producer id = " + Thread.currentThread().getId());
try {
while (isRuning){
Thread.sleep(r.nextInt(SLEEPTIME));
data = new PCData(count.incrementAndGet()); //原子的方式:相當於 a = ++b
System.out.println(data + " is put into queue");
if(!queue.offer(data, 2, TimeUnit.SECONDS)){ //放入隊列中,如果超時2秒就返回false,不再放入隊列中
System.err.println("failed to put data:" + data);
}
}
}catch (InterruptedException e){
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
public void stop(){
isRuning = false;
}
- Consumer:消費者,用於提取消息,並平方處理
public class Consumer implements Runnable{
private BlockingQueue<PCData> queue;
private static final int SLEEPTIME = 1000;
public Consumer(BlockingQueue<PCData> queue){
this.queue = queue;
}
@Override
public void run() {
Random r = new Random();
try {
while (true){
PCData data = queue.take(); //提取任務
if (data != null){
int re = data.getData() * data.getData();
System.out.printf("%d * %d = %d \n", data.getData(), data.getData(), re);
Thread.sleep(r.nextInt(SLEEPTIME));
}
}
}catch (InterruptedException e){
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
- 主方法的調用
public static void main(String[] args) throws InterruptedException {
BlockingQueue<PCData> queue = new LinkedBlockingDeque<PCData>(10);
//創建3個生產者
Producter producter1 = new Producter(queue);
Producter producter2 = new Producter(queue);
Producter producter3 = new Producter(queue);
//創建3個消費者
Consumer consumer1 = new Consumer(queue);
Consumer consumer2 = new Consumer(queue);
Consumer consumer3 = new Consumer(queue);
ExecutorService service = Executors.newCachedThreadPool();
service.execute(producter1);
service.execute(producter2);
service.execute(producter3);
service.execute(consumer1);
service.execute(consumer2);
service.execute(consumer3);
Thread.sleep(10 * 1000);
producter1.stop();
producter2.stop();
producter3.stop();
Thread.sleep(3000);
service.shutdown();
}
總結
上面代碼很簡單,這裏主要是提供一種解決方案的思路
- 生產者-消費者模式可以解決性能差異問題
- 同時也很好的解耦了生產者和消費者的關係