Map or Set
-
并發(fā)要求低時(shí)加鎖容器類:
Hashtable //用的少
Collections.sychronizedMap(new HashMap())
Collections.sychronizedList ...
例:List<String> strsSync = Collections.synchronizedList(new ArrayList()); 并發(fā)要求高時(shí)加鎖容器類:
ConcurrentHashMap
分段加鎖(大鎖分成小鎖)。不同塊之間可以同時(shí)執(zhí)行
并發(fā)要求高并需要排序:
ConcurrentSkipListMap
跳表查詢,查找效率高。跳表:每個(gè)元素上有多個(gè)指針,指向后面多個(gè)節(jié)點(diǎn),進(jìn)行跳躍查詢。比如查找 19.從6 開(kāi)始比較。大于6.直接跳到9.越過(guò)了7.從時(shí)間復(fù)雜度來(lái)講。從O(n)變?yōu)榱薕(n/2)
隊(duì)列
Collections.synchronizedXXX
CopyOnWriteList:
寫(xiě)時(shí)復(fù)制容器。寫(xiě)時(shí)效率很低。讀時(shí)效率高。寫(xiě)時(shí)加鎖,讀不加鎖。寫(xiě)的時(shí)候復(fù)制一份數(shù)據(jù),并在這份數(shù)據(jù)上做更改,再把指針指向換到新數(shù)據(jù)中。讀寫(xiě)分離的思路。
Queue: 分兩種:1.加鎖的Queue 2.Blocking Queue
-
CocurrentLinkedQueue //concurrentArrayQueue
例:
Queue<String> strs = new ConcurrentLinkedQueue<>();
for(int i=0; i<10; i++) {
strs.offer("a" + i); //add 有boolean返回值來(lái)判斷插入是否成功
}
System.out.println(strs.size()); //10
System.out.println(strs.poll());//a0 ;拿取第一個(gè)。并刪除。先進(jìn)先出
System.out.println(strs.size());//9
System.out.println(strs.peek());//a1 ;拿取第一個(gè)。不刪除
System.out.println(strs.size());// 9
-
BlockingQueue:阻塞隊(duì)列
LinkedBlockingQueue
ArrayBlockingQueue
例:
public class LinkedBlockingQueue {
static BlockingQueue<String> strs = new LinkedBlockingQueue<>(10);
static Random r = new Random();
public static void main(String[] args) {
new Thread(() -> {
for (int i = 0; i < 100; i++) {
try {
strs.put("a" + i); //如果滿了,就會(huì)等待
System.out.println("now size:"+strs.size()); //永遠(yuǎn)不會(huì)超過(guò)10個(gè)長(zhǎng)度
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "p1").start();
for (int i = 0; i < 5; i++) {
new Thread(() -> {
for (;;) {
try {
System.out.println(Thread.currentThread().getName() + " take -" + strs.take()); //如果空了,就會(huì)等待。不會(huì)出現(xiàn)IndexOutOfBoundException
TimeUnit.MILLISECONDS.sleep(r.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "c" + i).start();
}
}
}
往容器內(nèi)加入方法有多個(gè),如下
strs.put("aaa"); //滿了就會(huì)等待,程序阻塞
strs.add("aaa"); //報(bào)異常
strs.offer("aaa"); //不會(huì)報(bào)異常。只會(huì)在返回值中返回true or false
strs.offer("aaa", 1, TimeUnit.SECONDS);//等待一秒再加入
TransferQueue :隊(duì)列有消費(fèi)者等待消費(fèi)時(shí),直接把信息給消費(fèi)者,不進(jìn)入隊(duì)列,高并發(fā)下效率更高,適用于游戲服務(wù)器接收,轉(zhuǎn)發(fā)消息。如果沒(méi)有消費(fèi)者等待消費(fèi)該隊(duì)列,這時(shí)strs.transfer("aaa"); 線程將阻塞。但是put add 方法都不會(huì)阻塞。netty中使用比較多,很多實(shí)時(shí)消息需要強(qiáng)制被消費(fèi)之后才執(zhí)行下面操作。
SynchronusQueue : 容量為0,只能調(diào)用strs.put("aaa") 進(jìn)行加入,目的是為了進(jìn)入阻塞狀態(tài),等待被消費(fèi)。是必須被消費(fèi)的,不能存在隊(duì)列中。如調(diào)用add()將提示隊(duì)列已滿
DelayQueue : 可作為執(zhí)行定時(shí)任務(wù) 按指定的時(shí)間,順序消費(fèi),delay時(shí)間越短的越早消費(fèi)