并发容器简介

来源:互联网 发布:淘宝极有家有假货么 编辑:程序博客网 时间:2024/06/05 11:30

CurrentHashMap: 线程安全的HashMap

另一种线程安全的HashMap

public static Map m = Collections.synchronizedMap(new HashMap());//实现方式//但并发性不高public V get(Object key) {     synchronized (mutex) {return m.get(key);}}

CopyOnWriteArrayList: 适用于读多写少的场合,性能好于Vector

只有写写之间是会阻塞的。在写入的时候会进行一次自我复制,将修改的内容写入副本中,写完之后,再将修改完的副本替换原来的数据。

//读取private volatile transient Object[] array;public E get(int index){    return get(getArray(), index);}final Object[] getArray(){    return array;}private E get(Object[] a, int index){    return (E) a[index]}//写入public boolean add(E e) {    final ReentrantLock lock = this.lock;    lock.lock();    try {        Object[] elements = getArray();        int len = elements.length;        Object[] newElements = Arrays.copyOf(elements, len + 1);        newElements[len] = e;        setArray(newElements);        return true;    } finally {        lock.unlock();    }}

ConcurrentLinkedQueue: 线程安全的链表队列

这是在高并发环境下性能最好的队列了,前提是高并发(至少1000个线程)

(据测试,性能和Vector差不了多少)

//链表节点private static class Node<E>{    volatile E item;    volatile Node<E> next;}//tail代表的节点,可能会有延时现象,即tail并不是指向最后一个节点。//每次更新会跳跃两个元素来更新tail指针//    head == tail//    head(== tail) -> Node//    head -> Node -> Node(tail)//    head -> Node -> Node(tail) -> Node//    head -> Node -> Node -> Node -> Node(tail) public boolean offer(E e) {        checkNotNull(e);        final Node<E> newNode = new Node<E>(e);        for (Node<E> t = tail, p = t;;) {            Node<E> q = p.next;            if (q == null) {                // p是最后一个节点                if (p.casNext(null, newNode)) {                    //每两次更新一下tail                    if (p != t) // hop two nodes at a time                        casTail(t, newNode);  // Failure is OK.                    return true;                }                //如果CAS失败了,会在循环中再次尝试            }            else if (p == q)                //遇到哨兵节点,从head开始便历                //但如果tail被修改了,则使用tail(因为可能被修改正确了)                p = (t != (t = tail)) ? t : head;            else                //取下一个节点或者最后一个节点                p = (p != t && t != (t = tail)) ? t : q;        }    }    public E poll() {        restartFromHead:        for (;;) {            for (Node<E> h = head, p = h, q;;) {                E item = p.item;                if (item != null && p.casItem(item, null)) {                    // Successful CAS is the linearization point                    // for item to be removed from this queue.                    if (p != h) // hop two nodes at a time                        updateHead(h, ((q = p.next) != null) ? q : p);                    return item;                }                else if ((q = p.next) == null) {                    updateHead(h, p);                    return null;                }                else if (p == q)                    continue restartFromHead;                else                    p = q;            }        }    }    //设置当前的Node的item值,当cmp==当前值,设置为val    boolean casItem(E cmp,E val){        return UNSAFE.compareAndSwapObject(this,itemOffset,cmp,val);    }    //    void lazySetNext(Node<E> val){        UNSAFE.putOrderedObject(this, nextOffset,val);    }    boolean casNext(Node<E> cmp, Node<E> val){        return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);    }    final void updateHead(Node<E> h,Node<E> p){        if(h != p && casHead(h,p)            h.lazySetNext(h);w    }

BlockingQueue: 一个接口,堵塞队列,作为数据共享的通道。就想物业的人设立一个邮箱,业主可以往这个邮箱里面投递投诉意见。业主会变,物业的工作人员也会变,但是信箱的作用不变。

实现接口的类有ArrayBlockingQueue和LinkedBlockingQueue。ArrayBlockingQueue适合实现有界队列,而LinkedBlockingQueue适合实现无界队列。

offer():将元素放入队列尾,满了会返回false || poll(): 头部取出一个元素,队列空返回null

put():将元素放入队列尾,满了会一直等待,直到有空闲 || take(): 头部取出,队列空则堵塞等待

public void put(E e) throws InterruptedException {        checkNotNull(e);        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == items.length)                notFull.await();            enqueue(e);        } finally {            lock.unlock();        }    }public E take() throws InterruptedException {        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == 0)                notEmpty.await();            return dequeue();        } finally {            lock.unlock();        }    }public boolean offer(E e) {        checkNotNull(e);        final ReentrantLock lock = this.lock;        lock.lock();        try {            if (count == items.length)                return false;            else {                enqueue(e);                return true;            }        } finally {            lock.unlock();        }    }public E poll() {        final ReentrantLock lock = this.lock;        lock.lock();        try {            return (count == 0) ? null : dequeue();        } finally {            lock.unlock();        }    }

ConcurrentSkipListMap: 跳表的实现

最低层的链表维护了跳表的所有元素,上一层链表为下一层链表的子集。跳表的元素都是有序的,查找时从顶层链表开始查找,发现被查找的元素大于当前链表的中的取值,则会进入下一层链表进行查找。

跳表是一种空间换时间的实现,但比HashMap好的是,跳表是有序的。

原创粉丝点击