LinkedList線程不安全處理

1、舊的線程安全的集合

任何集合類均可以經過使用同步包裝器變成線程安全的:java

List<E> synchArrayList = Collections.synchronizedList(new ArrayList<E>());

Map<K,V> synchMap = Collections.synchronizedList(new HasMap<K,V>());

結果集合的方法使用鎖加以保護,提供線程安全的訪問。算法

若是在另外一個線程可能進行修改時要對集合進行迭代,任然須要使用封鎖。安全

synchronized(synchHashMap)
{
    Iterator<K> iter = synchHashMap.keySet().iterator();
    while(iter.hasNext())
        //遍歷
}

若是使用for each 循環必須使用一樣的代碼,由於循環使用了迭代器。若是在迭代的過程當中另外一個線程修改集合,迭代器會失效,拋出ConcurrentModificationException異常,所以併發的修改能夠被可靠的檢測出來。數據結構

2、高效的映像、集合和隊列

java.util.concurrent包提供了映像、有序集和隊列的高效實現:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentLinkedQueue。這些集合經過複雜的算法,經過容許併發的訪問數據結構的不一樣部分來使競爭極小化。併發

這些集合返回弱一致性的迭代器。這意味着迭代器不必定能反映出他們被構造以後的全部的修改,可是,他們不會將同一個值返回兩次,也不會拋出ConcurrentModificationException的異常。socket

package com.jie.concurrent;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

/**
 *
 * ConcurrentLinkedQueue是「線程安全」的隊列,而LinkedList(ArrayList)是非線程安全的。
 *
 *   下面是「多個線程同時操做而且遍歷queue」的示例
 *   (01) 當queue是ConcurrentLinkedQueue對象時,程序能正常運行。
 *   (02) 當queue是LinkedList對象時,程序會產生ConcurrentModificationException異常。
 *
 * \* Created with IntelliJ IDEA.
 * \* User: wugong.jie
 * \* Date: 2018/3/12 12:53
 * \* To change this template use File | Settings | File Templates.
 * \* Description:
 * \
 */
public class ConcurrentDemo {
    // queue是LinkedList對象時,程序會出錯。
    private static Queue<String> queue = new LinkedList<String>();
//    private static Queue<String> queue = new ConcurrentLinkedQueue<String>();
    public static void main(String[] args) {

        // 同時啓動兩個線程對queue進行操做!
        new MyThread("ta").start();
        new MyThread("tb").start();
    }

    private static void printAll() {
        String value;
        Iterator iter = queue.iterator();
        while(iter.hasNext()) {
            value = (String)iter.next();
            System.out.print(value+", ");
        }
        System.out.println();
    }
    private static class MyThread extends Thread {
        MyThread(String name) {
            super(name);
        }
        @Override
        public void run() {
            int i = 0;
            while (i++ < 6) {
                // 「線程名」 + "-" + "序號"
                String val = Thread.currentThread().getName()+i;
                queue.add(val);
                // 經過「Iterator」遍歷queue。
                printAll();
            }
        }
    }

}

結果:多運行幾回就出現下面的錯誤ide

Connected to the target VM, address: '127.0.0.1:1735', transport: 'socket'
Exception in thread "tb" ta1, tb1, 
ta1, tb1, ta2, 
ta1, ta1, tb1, ta2, ta3, 
ta1, tb1, ta2, ta3, ta4, 
ta1, tb1, ta2, ta3, ta4, ta5, 
ta1, tb1, ta2, ta3, ta4, ta5, ta6, 
Disconnected from the target VM, address: '127.0.0.1:1735', transport: 'socket'
java.util.ConcurrentModificationException
	at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
	at java.util.LinkedList$ListItr.next(LinkedList.java:888)
	at com.jie.concurrent.ConcurrentDemo.printAll(ConcurrentDemo.java:37)
	at com.jie.concurrent.ConcurrentDemo.access$100(ConcurrentDemo.java:22)
	at com.jie.concurrent.ConcurrentDemo$MyThread.run(ConcurrentDemo.java:54)

Process finished with exit code 0
相關文章
相關標籤/搜索