今天看啥  ›  专栏  ›  龙衣袭

ArrayList add() 数组指针越界?原来是线程同步问题

龙衣袭  · 简书  ·  · 2018-12-20 21:32

今天在看友盟控制台的时候发现一个崩溃,报错的是ArrayList add()数组指针越界??ArrayList不是动态扩容的吗?怎么会数组越界呢??带着问题,开始了今天的文章。

这是崩溃日志.png

看到这个错误,我第一时间就去谷歌了一下,找到了这篇文章 :

ArrayList在多线程调用Add()添加元素时的下标越界问题(java.lang.ArrayIndexOutOfBoundsException)

基本上这个文章已经告诉了我们答案,为什么 ArrayList 集合在add 的时候会数组越界。

我这里出现这个问题的原因是在网络请求的时候,使用了线程池去发送请求网络数据,在得到结果之后解析结果。

这里出错就是在解析结果的时候没有做同步操作引起的。

之所以要做同步操作是因为我多做了一步操作,就是网络不好的时候会多发几次网络请求,有时候可能已经返回了结果但是还是会再次发一次请求。

(吐槽一下,这个项目的网络请求是公司自己封装的 HttpConection 实现的,用起来还是挺费劲的)

上面的文章说了是线程同步的问题,但是作者没给出答案,我这里想到了几个解决办法。

  • 给方法加锁 synchronized
  • 使用Vector替代 ArrayList
  • 使用 CopyOnWriteArrayList 替代 ArrayList

PS: 以上几种实现方式各有优缺点,可在文末找到链接介绍。

我这里的解决办法是给方法加上 synchronized 锁,然后将用 Vector 替代了 ArrayList。

之前在听一个算法课的时候有听到 arrayList 的默认长度是10,且每次扩容都是原来的 1.5倍,趁着这次看源码,我就去找了对应的实现。

默认容量是 10
private static final int DEFAULT_CAPACITY = 10;

elementData是个动态数组,扩容为原来 1.5

image.png

ArrayList 常用方法

在验证了以上两点之后,我在源码中又看到了常见的一些方法,结合网上的归纳整理如下:

  • 增加元素到链表中
    boolean add(Element e)

    增加指定元素到链表尾部.

    void add(int index, Element e)

    增加指定元素到链表指定位置.
  • 从链表中删除元素
    void clear()

    从链表中删除所有元素.

    E remove(int index)

    删除链表中指定位置的元素.

    protected void removeRange(int start, int end)

    删除链表中从某一个位置开始到某一个位置结束的元素。
  • 获取链表中的元素
    E get(int index)

    获取链表中指定位置处的元素.

    Object[] toArray()

    获取一个数组,数组中所有元素是链表中的元素.(即将链表转换为一个数组)
  • 修改某个元素
    E set(int index, E element)

    将链表中指定位置上的元素替换成新元素。
  • 搜索元素
    boolean contains(Object o)

    如果链表包含指定元素,返回true.

    int indexOf(Object o)

    返回元素在链表中第一次出现的位置,如果返回-1,表示链表中没有这个元素。

    int lastIndexOf(Object o)

    返回元素在链表中最后一次出现的位置,如果返回-1,表示链表中没有这个元素。
  • 检查链表是否为空
    boolean isEmpty()

    返回true表示链表中没有任何元素.
  • 获取链表大小
    int size()

    返回链表长度(链表包含元素的个数).

遍历

获取链表之后我们经常会对其进行遍历,这里列举出三种遍历方式。

第一种,通过迭代器遍历。即通过 Iterator 去遍历。

image.png

第二种,随机访问,通过索引值去遍历。

由于 ArrayList 实现了 RandomAccess 接口,它支持通过索引值去随机访问元素。

image.png

第三种,for循环遍历。如下:

image.png

三种遍历方式中耗时最短的是使用随机访问,使用迭代器遍历的耗时最长。

参考

ArrayList用法
Java入门系列:实例讲解ArrayList用法

Vector 详解
Java 集合系列06之 Vector详细介绍(源码解析)和使用示例

ArrayList 详解
Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例

CopyOnWrite 详解
CopyOnWrite 详解

List总结
List总结(LinkedList, ArrayList等使用场景和性能分析)

本文完~,欢迎你留言和我一起讨论。




原文地址:访问原文地址
快照地址: 访问文章快照