常用的线程不安全集合:
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中的不安全集合类(二)
本人小白,如有编写不合理的地方请大神指点,轻喷