记遇到的一次system error问题,主要还是ArrayList的线程安全问题
1、问题:
今天在进行页面点击的时候,突然出现了个system error弹出提示,而且经过多次点击之后,发现并不是每次都会有这个报错,很偶然的才会有一次报错,所以首先想到应该是跟多线程有关,不然不可能出现随机的错误
2、解决:
所以就去看日志,发现报错的是这个地方:
Arrays.sort(taskTimes);
在行代码里抛出了空指针异常,那就说明在 taskTimes 这个List对象里肯定是有空元素,于是就向上找插入List的地方,发现在插入时使用了并发流:
List<Integer> taskTimes = new ArraysList<>();
boxs.parallelStream().forEach(box ->{
taskTimes.add(box.getScore);
});
这就很明确了,在使用 parallelStream() 的时候,其底层其实是使用了forkjoin线程池进行多线程执行,往ArrayList里并发插入肯定会出问题,在ArrayList里有这样一行代码,
element[size++] = e;
其实就是将e的值传入到element数组中,但是size是全局变量,在多线程情况下,size的值会出现异常,导致element中有元素为null,或者是数组越界,因此,我选择使用:
CopyOnWriteArrayList
或
Collections.synchronizedList(new ArrayList())
来替代,具体使用哪个主要看个人了,
CopyOnWriteArrayList 是基于复制来实现线程安全,会先复制出来一个List,然后把新元素加进去,后把指针从原来的List改为指向新List;
Collections.synchronizedList(new ArrayList())就是将原来的ArrayList中的方法都加个synchronized,要是以前可能会觉得比较重,但是后来 synchronized 优化过了,所以性能上应该也还可以。