簡略的翻看一下concurrent包,一部分是經過繼承AbstractQueuedSynchronizer實現(ReentrantLock、CountDownLatch、semaphore等),一部分經過lock實現(CycliBarrier、atomic、blockingqueue、concurrentMap等)。抽象類AbstractQueuedSynchronizer又主要是經過一個自定義的Node的自定義隊列來存儲線程,而後經過unsafe類(native)來實現指令級別的compare and swap獲取對內存中的共享區域控制權(也就是鎖)。而後unpark、park操做線程的入隊、出隊(在Node上解釋的使用一個FIFO的CLH對列來存放)。如今描述下concurrent中的集合和atomic。
html
原子量:保證了CPU讀、修改、寫。可是不保證可見性,數據不知道是刷新到主存仍是緩存。包括了:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference、AtomicStamped、AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。
java
atomic變量都是使用
算法
private volatile int value;
做爲存儲量,而後利用本地方法:unsafe中的compareAndSwapInt()等方法來修改內存中的數據,從而達到原子操做的功能。數組
blockingQueue集合是concurrent最有用的工具集合之一。它運行線程從一邊存放、一邊讀取。而且讀爲空、寫滿的狀況都會阻塞。緩存
這個接口主要有下面的方法
安全
這個接口衍生出來了ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronouseQueue等集合。
併發
其中最經常使用的的ArrayBlockQueue、LinkedBlockingQueue是經過
高併發
//ArrayBlockingQueue final Object[] items; final ReentrantLock lock; private final Condition notEmpty; private final Condition notFull; //LinkedBlockingQueue static class Node<E>; //鏈表節點 private final ReentrantLock takeLock = new ReentrantLock(); private final Condition notEmpty = takeLock.newCondition(); private final ReentrantLock putLock = new ReentrantLock(); private final Condition notFull = putLock.newCondition();
實現的。也就是一個生產消費者模式。而且它們是線程安全、在高併發的狀況下推薦使用,代替arrayList、linkedList。
工具
ConcurrentHashMap:使用的是「分段鎖」。同時使用segment來存放數據,每個k都會更加hash算法,計算出不一樣的segment。在segment裏面使用lock來加鎖,直接將一個打得map集合,分散成很小的map數組,減小了佔用時間。atom
concurrentHashMap的誕生用來在高併發的條件下代替hashTable(hashmap的synchronized版)。
應用:
ConcurrentMap concurrentMap = new ConcurrentHashMap(); concurrentMap.put("key", "value"); Object value = concurrentMap.get("key");
查看源碼:經過實現一個靜態嵌入內部類實現存儲節點
static class Node<K,V> implements Map.Entry<K,V> { final int hash; //key的hash值,用來快速定位查找的對象的位置 final K key; volatile V val; volatile Node<K,V> next; }
而且,在兌取對象時並不會把整個Map鎖住(經過unsafe的getObjectVolatile()方法)。此外,向其寫入對象的時候,也不會將全部的數據鎖住。
大概流程:concurrentHashMap會建立一個Node<K,V>[]出來存放Node<K,V>的鏈表地址。而後在存放、讀取的時候經過神奇的unsafe指令(直接操做指令)來肯定key.hash表明的Node<K,V>的地址,而且鎖住它。這樣就不會鎖住整個concurrentHashMap了。以下圖
concurent教程:http://tutorials.jenkov.com/java-util-concurrent/index.html