一避诽、什么是阻塞隊列
1.1 簡介
阻塞隊列(BlockingQueue)是用于進程間通信或同一進程內(nèi)的線程間通信的組件盆繁。它的工作原理是當隊列是空的時虚倒,線程試圖從隊列中獲取元素的操作將會被阻塞园爷,或者當隊列是滿時浴骂,線程往隊列里添加元素的操作會被阻塞钱磅。阻塞隊列最常用于生產(chǎn)消費模式中梦裂,生產(chǎn)者是往隊列里添加元素的線程,消費者是從隊列里拿元素的線程盖淡。
1.2 常用操作方法
最近在看方騰飛的《Java并發(fā)編程藝術》書籍年柠,書中作者對阻塞隊列常用的四種處理方法歸納的非常清晰。四種處理方法如下:
處理方式 | 拋出異常 | 返回特殊值 | 一直阻塞 | 超時退出 |
---|---|---|---|---|
插入方法 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除方法 | remove() | poll() | take() | poll(time,unit) |
檢查方法 | element() | peek() | 不可用 | 不可用 |
- 拋出異常:是指當阻塞隊列滿時候褪迟,再往隊列里插入元素冗恨,會拋出IllegalStateException(“Queue full”)異常。當隊列為空時味赃,從隊列里獲取元素時會拋出NoSuchElementException異常 掀抹。
- 返回特殊值:插入方法會返回是否成功,成功則返回true心俗。移除方法傲武,則是從隊列里拿出一個元素,如果沒有則返回null
- 一直阻塞:當阻塞隊列滿時城榛,如果生產(chǎn)者線程往隊列里put元素揪利,隊列會一直阻塞生產(chǎn)者線程,直到拿到數(shù)據(jù)吠谢,或者響應中斷退出土童。當隊列空時,消費者線程試圖從隊列里take元素工坊,隊列也會阻塞消費者線程献汗,直到隊列可用。
- 超時退出:當阻塞隊列滿時王污,隊列會阻塞生產(chǎn)者線程一段時間罢吃,如果超過一定的時間,生產(chǎn)者線程就會退出昭齐。
1.3 Java里的阻塞隊列
JDK7提供了7個阻塞隊列尿招。分別是
- ArrayBlockingQueue :一個由數(shù)組結(jié)構(gòu)組成的有界阻塞隊列。
- LinkedBlockingQueue :一個由鏈表結(jié)構(gòu)組成的有界阻塞隊列阱驾。
- PriorityBlockingQueue :一個支持優(yōu)先級排序的無界阻塞隊列就谜。
- DelayQueue:一個使用優(yōu)先級隊列實現(xiàn)的無界阻塞隊列。
- SynchronousQueue:一個不存儲元素的阻塞隊列里覆。
- LinkedTransferQueue:一個由鏈表結(jié)構(gòu)組成的無界阻塞隊列丧荐。
- LinkedBlockingDeque:一個由鏈表結(jié)構(gòu)組成的雙向阻塞隊列。
1.4 為什么用隊列喧枷?
如上圖它是一種線性列表虹统,以FIFO(先進先出)的順序訪問。由于隊列是線性列表隧甚,在查找元素時需要一個一個遍歷车荔,效率非常低,所以不適合做查詢操作戚扳,那么它的優(yōu)點在哪忧便?優(yōu)點在于他們每一個節(jié)點是串聯(lián)的,在移動或刪除元素時帽借,只需要修改節(jié)點指向的元素珠增,而在數(shù)組中當你刪除其中一個元素時,需要把該元素后邊所有元素位置重新排列宜雀,這就使得隊列在插入和刪除上效率要比數(shù)組中高切平,詳細如下圖所示。那么在游戲服務器開發(fā)中它的主要應用場景有哪一些辐董?比如:頻道聊天悴品,AOI、郵件群發(fā)等等简烘。
頻道聊天
玩家A在頻道發(fā)送消息-----> 服務器------->該頻道玩家看到了這個玩家A發(fā)的消息
AOI
玩家A在場景B對NPC使用技能-----> 服務器------->該場景B附近的玩家能看到玩家A在使用技能
使用消息隊列的十大理由:http://www.oschina.net/translate/top-10-uses-for-message-queue?cmp
1.5 代碼示例(頻道聊天)
package com.game.lll.queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class LinkedBlockingQueueTest{
public static final int WORLD = 0;//世界頻道
public static final int AREA = 1;//區(qū)域頻道
public static final int SYSTEM = 2;//系統(tǒng)消息
public static final String[] NAME = {"世界","區(qū)域","系統(tǒng)"};
protected BlockingQueue<ChatMessage> messages = new LinkedBlockingQueue<ChatMessage>();
private Producer producer1 = new Producer("小毛驢");
private Producer producer2 = new Producer("小兔子");
private Producer producer3 = new Producer("小貓咪");
private Consumer consumer = new Consumer();
public static void main(String[] args) {
LinkedBlockingQueueTest queueTest = new LinkedBlockingQueueTest();
queueTest.consumer.start();;
for(int i=0;i<10;i++){
new Thread(){
public void run() {
queueTest.producer1.addChatMessage("大家好苔严!", WORLD);
queueTest.producer2.addChatMessage("大家好!", AREA);
queueTest.producer3.addChatMessage("大家好孤澎!", SYSTEM);
};
}.start();
}
while(Thread.activeCount()>1) //保證前面的線程都執(zhí)行完
Thread.yield();
}
public class Producer
{
protected String name;
public Producer(String name) {
this.name = name;
}
public void addChatMessage(String message,int channel) {
messages.add(new ChatMessage(name, message, channel));
}
}
public class Consumer extends Thread{
@Override
public void run() {
while (true) {
try {
ChatMessage message = messages.take();
switch (message.channel) {
case WORLD:
//
break;
case AREA:
//
break;
case SYSTEM:
//
break;
default:
break;
}
System.out.println("【"+NAME[message.channel]+"】"+message.name+":"+message.message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class ChatMessage
{
protected String name;
protected String message;
protected int channel;
public ChatMessage(String name,String message,int channel)
{
this.name = name;
this.message = message;
this.channel = channel;
}
}
}
控制臺:
【世界】小毛驢:大家好届氢!
【世界】小毛驢:大家好!
【區(qū)域】小兔子:大家好覆旭!
【系統(tǒng)】小貓咪:大家好退子!
【世界】小毛驢:大家好岖妄!
【區(qū)域】小兔子:大家好!
【系統(tǒng)】小貓咪:大家好寂祥!
【世界】小毛驢:大家好荐虐!
【區(qū)域】小兔子:大家好!
【系統(tǒng)】小貓咪:大家好丸凭!
【世界】小毛驢:大家好福扬!
【區(qū)域】小兔子:大家好!
【系統(tǒng)】小貓咪:大家好惜犀!
【世界】小毛驢:大家好铛碑!
【區(qū)域】小兔子:大家好!
【系統(tǒng)】小貓咪:大家好虽界!
【世界】小毛驢:大家好汽烦!
【區(qū)域】小兔子:大家好!
【系統(tǒng)】小貓咪:大家好浓恳!
【世界】小毛驢:大家好刹缝!
【區(qū)域】小兔子:大家好!
【系統(tǒng)】小貓咪:大家好颈将!
【世界】小毛驢:大家好梢夯!
【區(qū)域】小兔子:大家好!
【系統(tǒng)】小貓咪:大家好晴圾!
【區(qū)域】小兔子:大家好颂砸!
【系統(tǒng)】小貓咪:大家好!
【世界】小毛驢:大家好死姚!
【區(qū)域】小兔子:大家好人乓!
【系統(tǒng)】小貓咪:大家好!
作者:小毛驢都毒,一個Java游戲服務器開發(fā)者 原文地址:https://liulongling.github.io/