多線程與高併發六-容器

容器圖

7616411c2983db72b19ba36a1f64f3d6

1、MAP

一、不須要同步的狀況

HashMap
TreeMap
LinkedHashMapjava

二、併發不高的狀況

Hashtable
Collections.synchronizedMap();數組

三、高併發的狀況

ConcurrentHashMap (分紅16段,而後給各段加鎖,多線程訪問小分段,因此效率高些)
ConcurrentHashSet
ConcurrentSkipListMap 跳錶,已排序,能夠用來快速查找多線程

2、LIST

一、不須要同步的狀況

ArrayList
LinkedList併發

二、併發的狀況

Vector
Collections.synchronizedList( )ide

CopyOnWriteList
寫時複製容器 copy on write 寫的時候,複製一份新的供讀
多線程環境下,寫時效率低,讀時效率高
適合寫少讀多的環境高併發

3、QUEUE

一、不須要同步的狀況

LinkedList
PriorityQueue性能

二、高併發的狀況

  1. 高性能隊列:CocurrentLinkedQueue / concurrentArrayQueuethis

  2. 阻塞隊列:BlockingQueue線程

    BlockingQueue能夠做爲多個線程之間的數據共享通道。3d

    a4b64a6ceaf3a5762979838e9e91a463

LinkedBlockingQueue:基於鏈表實現,適合作無界隊列或者邊界值很是的大隊列
ArrayBlockingQueue(int capacity):基於數組實現,適合作有界隊列

//滿了不會報異常,可是不會加進去
public boolean offer(E e) {
...
}
//若是滿了,就會等待,程序阻塞
public void put(E e) throws InterruptedException {
...
}
//滿了報異常
public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
}
//若是空了,就會等待,程序阻塞
public E take() throws InterruptedException {
...
}
//若是隊列爲空,直接返回null
public E poll() {
...
}

put() 和 take() 方法是體現 Blocking 的關鍵。

  1. 執行定時任務:DelayQueue
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
    implements BlockingQueue<E> {
}

示例:

static BlockingQueue<MyTask> tasks = new DelayQueue<>();

static class MyTask implements Delayed {
        long runningTime;       
        MyTask(long rt) {
            this.runningTime = rt;
        }

        @Override
        public int compareTo(Delayed o) {
            if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS))
                return -1;
            else if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) 
                return 1;
            else 
                return 0;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(runningTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public String toString() {
            return "" + runningTime;
        }
}
MyTask t1 = new MyTask(now + 5000);
tasks.put(t1);

DelayQueue是阻塞無界隊列,實現了BlockingQueue。默認排了序,每一個元素須要等一段時間才能被取出來,每一個元素本身會記錄時間,等待時間最短的排在前面,最早取出來。

  1. 轉發消息:TransferQueue
    TransferQueue是一個接口,實現類爲:LinkedTransferQueue
// 生產者有數據時首先看有沒有消費者,有的話,直接給消費者,不放進隊列了
// 沒有消費者的話 就阻塞在這裏,後面的代碼執行不了了
public void transfer(E e) throws InterruptedException {
        if (xfer(e, true, SYNC, 0) != null) {
            Thread.interrupted(); // failure possible only due to interrupt
            throw new InterruptedException();
        }
}

使用時需先啓動消費者,後啓動生產者。能夠用於實時消息處理。

  1. SynchronusQueue: 一種特殊TransferQueue,容量爲0
//阻塞等待消費者消費  用的是transfer
public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        if (transferer.transfer(e, false, 0) == null) {
            Thread.interrupted();
            throw new InterruptedException();
        }
}
//若是容量不爲0,報錯
public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
}
相關文章
相關標籤/搜索