首页 > 其他分享 >记遇到的一次system error问题,主要还是ArrayList的线程安全问题

记遇到的一次system error问题,主要还是ArrayList的线程安全问题

时间:2023-09-04 11:46:28浏览次数:32  
标签:ArrayList List system taskTimes 线程 报错 多线程

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 优化过了,所以性能上应该也还可以。


标签:ArrayList,List,system,taskTimes,线程,报错,多线程
From: https://www.cnblogs.com/Silentness/p/17676504.html

相关文章

  • ThreadLocal:线程中的全局变量
    最近接了一个新需求,业务场景上需要在原有基础上新增2个字段,接口新增参数意味着很多类和方法的逻辑都需要改变,需要先判断是否属于该业务场景,再做对应的逻辑。原本的打算是在入口处新增变量,在操作数据的时候进行逻辑判断将变量进行存储或查询。如果全链路都变更入参和结构,很明显代......
  • java多线程爬取笔趣阁所有小说
    可以选择下载的数量,全部下载下来够呛,首先没那么大的盘新版本:https://wws.lanzous.com/iAEMoghsgeb密码:7vjzjar包:https://wws.lanzous.com/ilphyghsgcj密码:f38a <dependency><!--jsoupHTMLparserlibrary[url=home.php?mod=space&uid=402414]@[/url]htt......
  • 多线程学习笔记
     1.进程和线程进程是指一个程序,例如QQ,打开会占用一定的内存和空间,会有产生和消亡。线程是由进程创造,一个进程可以有多个线程。单线程:在同一个时刻,只允许执行一个线程。多线程:在同一个时刻,允许执行多个线程。并发:同一时刻,多个任务交替执行,例如一台电脑同时运行qq和迅雷,看着貌似是有......
  • Java线程池面试题集
    以面试官视角万字解读线程池10大经典面试题!(这个链接里难的要命)线程池面试连环炮,你能抗住几题?(这个链接里比较正常)什么是线程池?为什么要使用线程池?线程池就是采用池化思想管理线程的工具。JUC为我们提供了ThreadPoolExecutor体系类来帮助我们管理线程、并行执行任务。顶级接......
  • WSL中无法使用systemctl命令
    WSL使用system报错"Systemhasnotbeenbootedwithsystemdasinitsystem"(原文链接)[https://linuxhandbook.com/system-has-not-been-booted-with-systemd/]原因ThereasonisthatyouaretryingtousesystemdcommandtomanageservicesonLinuxbutyoursy......
  • CUDA 线程ID 计算方式
    threadID的计算方式,简单来说很像小学学的除法公式,本文转载自同学一篇博客;并进行简单修改;被除数=除数*商+余数用公式表示:$$线程Id=blockId*blockSize+threadId$$blockId:当前block在grid中的坐标(可能是1维到3维)blockSize:block的大小,描述其中含有多少个thr......
  • JDK源码阅读:ArrayList原理
    ArrayList原理ArrayList集合底层数据结构ArrayList集合介绍List接口的可调整大小的数组实现。数组:一旦初始化长度就不可以发生改变数组结构特性增删慢:每次删除元素,都需要更改数组长度、拷贝以及移动元素位置。查询快:由于数组在内存中是一块连续空间,因此可以根据地址+索引的......
  • 四、进程与线程
    4.1进程、线程基础知识进程代码是存储在硬盘的静态文件,编译后生成可执行文件,可执行文件运行后被装载到内存中,这个运行中的程序被称为进程(Process)。么当运行到读取⽂件的指令时,就会去从硬盘读取数据,但是硬盘的读写速度是⾮常慢的,那么在这个时候,如果CPU只等硬盘返回数据别的什......
  • 《C++并发编程实战》读书笔记(2):线程间共享数据
    1、使用互斥量在C++中,我们通过构造std::mutex的实例来创建互斥量,调用成员函数lock()对其加锁,调用unlock()解锁。但通常更推荐的做法是使用标准库提供的类模板std::lock_guard<>,它针对互斥量实现了RAII手法:在构造时给互斥量加锁,析构时解锁。两个类都在头文件<mutex>里声明。std::......
  • Java常用四大线程池用法以及ThreadPoolExecutor详解(转)
    为什么用线程池?1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处-理效率2.线程并发数量过多,抢占系统资源从而导致阻塞3.对线程进行一些简单的管理在Java中,线程池的概念是Executor这个接口,具体实现为ThreadPoolExecutor类,学习Java中的线程池,就可以......