常用的線程不安全集合:
ArrayList
LinkedList
ArraySet
HashMap
線程不安全:
比如當A線程在操作數據時,B線程突然進來,A線程要添加的位置佔用,後續A線程將此數據(B線程的數據)修改爲自己的數據這時就會空值(java.lang.NullPointerException) 或者是拋出異常(java.util.ConcurrentModificationException)
JAVA版本:1.8
ArrayList 示例:
我們使用 15 個線程同時向 List 接口下 ArrayList 集合 中添加數據:
public static void main(String[] args) {
//新建一個ArrayList集合 strings
List<String> strings = new ArrayList<>();
//循環創建線程 向strings中添加數據
for (int i = 1; i <= 15; i++) {
new Thread(() -> {
strings.add(UUID.randomUUID().toString().substring(0, 5));
System.out.println(Thread.currentThread().getName()+":"+strings);
},String.valueOf(i)).start();
}
}
執行後我們看到:
Exception in thread "2" Exception in thread "5" java.util.ConcurrentModificationException
線程"2" 與 線程 “5” 拋出異常:
java.util.ConcurrentModificationException (併發修改異常)
我們來看 ArrayList 的add() 方法源碼一步步解析
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
ArrayLisrt 底層 爲一個數組
首先更新了 數組的長度,然後將我們的屬性賦給指定的數組下標
故:ArrayList 爲線程不安全集合
LinkedList 示例:
我們使用 15 個線程同時向 List 接口下 LinkedList 集合 中添加數據:
List<String> strings = new LinkedList<>();
執行後我們看到:
Exception in thread "12" Exception in thread "4" java.lang.NullPointerException
超過一半的線程拋出:
java.lang.NullPointerException (空指針異常)
我們來看 LinkedList 的add() 方法源碼一步步解析
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
LinkedList 底層是基於雙向鏈表實現的,也是實現了 List 接口,所以也擁有 List 的一些特點
可見每次插入都是移動指針
故:LinkedList 爲線程不安全集合
如何解決線程不安全問題請查看
Java中的不安全集合類(二)
本人小白,如有編寫不合理的地方請大神指點,輕噴