android多线程----同步集合

一、程序中的优化策略—-CopyOnWriteArrayList
Copy-On_Write 是一种用于程序设计中的优化策略,器基本思路是:
从多个线程共享同一个列表,当某个线程想要修改这个列表的元素时,会把列表的元素Copy一份,然后进行修改,修改完成之后在在将新的元素设置给这个列表,这是一种懒惰策略。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不要加锁,因为当前容器不会添加,移除任何元素。所以CopyOnWrite容器是一种读写分离的思想,读和写不同的容器。
下面是CopyOnWriteArrayList的add方法:

 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();
        }
    }

从程序中可以发现,在添加的时候进行了加锁操作,负责多线程写的时候会Copy出N个副本出来,复制一份之后将添加的新元素设置到元素数组的len位置,饭后把最新的元素数组设置给该列表。
读的时候不需要加锁,如果读的时候有多线程正在向CopyOnWriteArrayList添加数据,对还是会读到就得数据,因为写的时候不会锁住旧的元素数据。
get方法如下:

    public E get(int index) {
        return get(getArray(), index);
    }

与其类似的还有 CopyOnWirteArraySet

二、提高并发效率———-ConcurrentHashMap
使用锁分段技术,每一把锁用于锁容器其中的一部分数据,那么当多线程访问不同的数据段时,县城间就不会存在锁竞争,从而可以有效提高并发访问的效率。
附上put、get 方法,其中Segment为数据段

public V put(K key, V value) {
        Segment<K,V> s;
        if (value == null)
            throw new NullPointerException();
        int hash = hash(key);
        int j = (hash >>> segmentShift) & segmentMask;
        if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
             (segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment
            s = ensureSegment(j);
        return s.put(key, hash, value, false);
    }



public V get(Object key) {
        Segment<K,V> s; // manually integrate access methods to reduce overhead
        HashEntry<K,V>[] tab;
        int h = hash(key);
        long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
        if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
            (tab = s.table) != null) {
            for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
                     (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
                 e != null; e = e.next) {
                K k;
                if ((k = e.key) == key || (e.hash == h && key.equals(k)))
                    return e.value;
            }
        }
        return null;
    }

三、阻塞队列 ——–BlockingQueue
阻塞队列提供了一些特性,例如,当队列满了时,再次调用put函数添加元素,那么调用线程将会阻塞,直到队列不再是填满状态。这个特性很有用,它就是生产者—消费者一个实现。

add(e): 把元素e加到BlockingQueue里,如果BlockingQueue可以容纳,则返回true,否则抛出异常。

offer(e): 讲元素e添加到BlockingQueue里,如果BlockingQueue可以容纳,则返回true,否则返回false。

offer(e,time,unit): 将元素e添加到BlockingQueue里,如果BlockingQueue可以容纳,则返回true,否则在等待指定的BlockingQueue里面有空间再继续添加。

put(e):把元素e添加到BlockingQueue里,如果BlockingQueue不能容纳,则调用此方法的线程被阻塞直到BlockingQueue里面有空间再继续添加。

take() 取走BlockingQueue里排在队首的对象,若BlockingQueue为空,则进入等待状态直到Blocking有新的对象加入为止。

poll(time,unit):取出并移除队列中的队首元素,如果设定的阻塞时间内还未获得数据,那么返回null.

element() :获取队首元素,如果队列为空,那么抛出NoSuchElementException异常。

peek(): 获取队首元素,如果队列为空,那么返回null

remove(): 获取并移除队首元素,如果队列为空,那么抛出NoSuchElementException异常。

其主要实现有:
ArrayBlockingQueue 一个数组实现的、线程安全的、有界的阻塞队列。
LinkedBlockingQueue 一个单向链表实现的阻塞队列,该队列按FIFO排列元素,新元素插入到队列的尾部。
LinkedBlockingDeque 一个双向链表实现的双向并发阻塞队列,该队列同时支持FIFO和FILO两种操作方式。
还有ConcurrentLinkedQueue, 一个基于链接节点的无界线程安全队列。

你可能感兴趣的:(同步集合)