標籤:
一、程式中的最佳化策略—-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, 一個基於連結節點的無界安全執行緒隊列。
android多線程----同步集合