首页 > 其他分享 >ArrayList的线程安全问题简述,以及如何优化

ArrayList的线程安全问题简述,以及如何优化

时间:2023-10-05 16:34:02浏览次数:30  
标签:Thread ArrayList list 简述 线程 thread2 thread1 new

问题:

创建一个ArrayList,然后创建两个线程,每个线程for循环1000次向公共的List里面添加数据,在一个线程读取List当前的大小之后,另一个线程可能已经对List进行了修改。这样就可能导致数据的不一致性,例如一个线程读取到的List大小已经被另一个线程修改了,因此,在这个案例中,最终的列表大小可能不是期望值2000,而是一个小于或大于2000的随机值。这正是ArrayList线程不安全的一个典型表现。

 

解决方案:

1.使用Vector:Vector类与ArrayList类非常类似,但它的方法是同步的,可以确保在多线程环境中的安全访问和操作

Vector<Integer> list = new Vector<>();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("List size: " + list.size());
    }
}

 

2.使用CopyOnWriteArrayList:CopyOnWriteArrayList是Java提供的一个线程安全的并发集合类,它通过每次添加、修改或删除元素时创建一个新的底层数组来实现线程安全,这种机制叫做写时复制。

  CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("List size: " + list.size());
    }
}

 

标签:Thread,ArrayList,list,简述,线程,thread2,thread1,new
From: https://www.cnblogs.com/xialang/p/17743496.html

相关文章

  • 学习多进程多线程
    两个单词:Process进程、Thread线程线程的三种创建方式:1、继承Thread类   写一个子类去继承然后重写run()方法2、实现Runnable接口3、实现Callable接口  这个一般工作三到五年后才经常用到 1、创建一个线程对象,然后调用start()方法可以交替进行 要是用run()方......
  • 性能暴增70%!AMD线程撕裂者RPO 7000将于10月19日发布: 96核心Zen 4史无前例
    据wccftech最新报道,AMD的下一代RyzenThreadripper(线程撕裂者)PRO7000“StormPeak”CPU将于10月19日作为终极工作站解决方案亮相。据悉,线程撕裂者PRO7000是AMD基于Zen4架构的最新一代旗舰工作站CPU,它的推出也意味着基于Zen3的PRO5000系列将退出历史舞台。根据泄露的消息,预......
  • 进程栈、线程栈、内存栈、中断栈
    前言虽然我也很想讲X86_64体系,无奈这样的资料的确不多,因此本文还是本着学习的态度,探究早已经过时的X86体系。本文转载自此文,该博主对栈的数据结构、栈的作用等进行了阐述,其中涉及了函数栈帧的相关知识,这部分内容我没有转载,我仅仅转载了我感兴趣的进程栈,线程栈等部分,并在其中融入......
  • linux 进程切换和线程切换
    进程切换分两步:1.切换页目录以使用新的地址空间2.切换内核栈和硬件上下文对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的。切换的性能消耗:1、线程上下文切换和进程上下问切换一个最主要的区别是线程的切换虚拟内......
  • Java基础知识29--主线程、子线程执行顺序
    1、主线程与子线程互不影响最常见的情况,主线程中开启了一个子线程,开启之后,主线程与子线程互不影响各自的生命周期,即主线程结束,子线程还可以继续执行;子线程结束,主线程也能继续执行。publicclassTestThread{publicstaticvoidmain(String[]args)throwsInterruptedExcepti......
  • JavaSE(08) - 集合 - ArrayList
    JavaSE(08)-集合-ArrayListp111ArrayList基本使用创建集合对象,泛型:限定集合中的数据类型.在jdk7中,后面的<>中可以不写数据类型.集合在底层做了一些处理,打印对象不是地址值,而是集合中存储的内容.publicclassArrayListBasic{publicstaticvoidmain......
  • java多线程中的 锁(暂时记录)
    P150-lock----锁----那一节publicclassThreadExtendextendsThread{  staticintticket=0;  staticLocklock=newReentrantLock();  publicvoidrun(){    while(true){      lock.lock();      if(ticket......
  • samtools线程数对 sam文件转换为bam文件效率的影响
     001、(base)[b20223040323@admin1batch_test02]$ls##测试sam文件template.slurmtest.sam(base)[b20223040323@admin1batch_test02]$cattemplate.slurm##测试模板#!/bin/bash#SBATCH-Jxxxx#SBATCH-pCnode2##SBATCH-o%j.xxxx.r......
  • 如何回答线程安全
    前言在面试过程中,很多的面试官都喜欢开局先来一个说一下你对线程安全的认识。这个问题呢广度挺大的,不同人理解不同,回答不同。如果不能好好的接下这一招,那么面试官就可能对你们后面的期待大大减小。秋招在即,根据个人的见解和所查资料,对这一招进行拆招。(不一定是好招,仅为个人总结......
  • java---多线程[(重点)上]
    15.1概念以前写的程序都是单线程,main方法程序称为主线程,主线程的结束所有的子线程都会跟着结束。多线程就代表着一个程序可以去做多件事情。线程:一个程序去做多件事情,每件事情由一个线程去完成。进程:一个进程由多个线程组成,一个进程至少有一个线程。一个进程就是一个应用程序多线......