iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >怎么理解Java中JUC下的CopyOnWriteArrayList
  • 883
分享到

怎么理解Java中JUC下的CopyOnWriteArrayList

2024-04-02 19:04:59 883人浏览 泡泡鱼
摘要

这篇文章主要讲解了“怎么理解Java中JUC下的CopyOnWriteArrayList”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Java中JU

这篇文章主要讲解了“怎么理解Java中JUC下的CopyOnWriteArrayList”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Java中JUC下的CopyOnWriteArrayList”吧!

ArrayList 是我们常用的工具类之一,但是在多线程的情况下,ArrayList 作为共享变量时,并不是线程安全的。主要有以下两个原因:

  • 1、 ArrayList 自身的 elementData、size、modCount 在进行操作的时候,都没有加

  • 2、这些变量没有被 volatile 修饰,在多线程的情况下,对这些变量操作可能会出现值被覆盖的情况;

如果我们想在多线程情况下使用 ArrayList 怎么办?有以下几种办法:

  • 使用 Collections.SynchronizedList ;

  • 使用 JUC 下的 CopyOnWriteArrayList;

怎么理解Java中JUC下的CopyOnWriteArrayList

先来看看 SynchronizedLis,Collections 其实就是对 ArrayList 进行了一个加锁包装,这个从源码中可以看出;

...部分源码,完整源码请查看 jdk 源码...
public void add(int index, E element) {
   synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
   synchronized (mutex) {return list.remove(index);}
}

对于 Collections.SynchronizedList 比较简单,就是锁包装了一下,就不多说了~

CopyOnWriteArrayList 也是 JUC 下面的一个并发容器类。不知道你发现没有,但凡你常用的集合类,在 JUC 下基本上都可以找到一个并发类,比如 HashMap 有对应的 ConcurrentHashMap。

CopyOnWriteArrayList 跟 ArrayList 在整体架构上并没有什么区别,底层都是基于数组实现的。不同的地方大概有两点:

  • 底层数组被 volatile 关键字修饰;

  • 对数组进行数据变更时加锁;

CopyOnWriteArrayList 的加锁操作跟 Collections.SynchronizedList 简单的加锁还不一样,CopyOnWriteArrayList 中的加锁过程还是非常值得学习的。CopyOnWriteArrayList 的加锁过程,大概可以概括为以下四步:

  • 1、加锁;

  • 2、从原数组中拷贝出新数组;

  • 3、在新数组上进行操作,并把新数组赋值给数组容器;

  • 4、解锁;

结合源码来深入了解 CopyOnWriteArrayList 的并发实现,我们选择 ArrayList 最简单的将元素新增数组尾部的操作来分析实现过程,源码如下:


public boolean add(E e) {
// 获取锁,注意这是全局锁
   final ReentrantLock lock = this.lock;
   // 加锁操作
   lock.lock();
   try {
   // 获取数组
       Object[] elements = getArray();
       int len = elements.length;
       // 将数组内容拷贝到新数组中
       Object[] newElements = Arrays.copyOf(elements, len + 1);
       // 对新数组操作
       newElements[len] = e;
       // 变更底层数组的引用
       setArray(newElements);
       return true;
   } finally {
   // 解锁
       lock.unlock();
   }
}

CopyOnWriteArrayList 就是通过加锁来说实现容器安全的,可能你会有疑问,为什么引入一个新数组,数组的拷贝还是消耗时间的,直接在原数组上操作不就好了吗?。主要原因有以下两点:

  • volatile 关键字修饰的是数组,如果我们简单的在原来数组上修改其中某几个元素的值,是无法触发可见性的,我们必须通过修改数组的内存地址才行,也就说要对数组进行重新赋值才行。

  • 在新的数组上进行拷贝,对老数组没有任何影响,只有新数组完全拷贝完成之后,外部才能访问到,降低了在赋值过程中,老数组数据变动的影响。比如经典的 ConcurrentModificationException 异常问题。

其他的新增方法就自己去查看源码了,相差不多,基本上是一样的。对数组的删除跟新增都是差不多,不同的地方是在删除了时候,赋值给新数组时会出现不同的选择策略。我把源码贴上:

public E remove(int index) {
   final ReentrantLock lock = this.lock;
   // 加锁
   lock.lock();
   try {
       Object[] elements = getArray();
       int len = elements.length;
       E oldValue = get(elements, index);
       // 先计算出要移动的问题
       int numMoved = len - index - 1;
       // 根据移动的位置选择策略
       if (numMoved == 0)
           setArray(Arrays.copyOf(elements, len - 1));
       else {
           Object[] newElements = new Object[len - 1];
           System.arraycopy(elements, 0, newElements, 0, index);
           System.arraycopy(elements, index + 1, newElements, index,
                            numMoved);
           setArray(newElements);
       }
       return oldValue;
   } finally {
      //解锁
       lock.unlock();
   }
}

感谢各位的阅读,以上就是“怎么理解Java中JUC下的CopyOnWriteArrayList”的内容了,经过本文的学习后,相信大家对怎么理解Java中JUC下的CopyOnWriteArrayList这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 怎么理解Java中JUC下的CopyOnWriteArrayList

本文链接: https://www.lsjlt.com/news/85029.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么理解Java中JUC下的CopyOnWriteArrayList
    这篇文章主要讲解了“怎么理解Java中JUC下的CopyOnWriteArrayList”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Java中JU...
    99+
    2022-10-19
  • java项目中实现CopyOnWriteArrayList并发容器的原理是什么
    今天就跟大家聊聊有关java项目中实现CopyOnWriteArrayList并发容器的原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。CopyOnWriteArrayLis...
    99+
    2023-05-31
    java copyonwritearraylist 并发容器
  • JUC中的Lock锁与synchronized同步代码块问题怎么解决
    这篇文章主要介绍“JUC中的Lock锁与synchronized同步代码块问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JUC中的Lock锁与synchronized同步代码块问题怎么解...
    99+
    2023-06-29
  • 怎么理解Java中的JSP
    本篇内容介绍了“怎么理解Java中的JSP”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言:JSP 代表 Java 服务器页面。它是一种在...
    99+
    2023-06-25
  • java中的for怎么理解
    java关键字for:循环控制的一个关键字,可以用来控制语句循环。通常的格式是:for(初始化;控制语句;控制变量调控){循环语句}。控制变量的初始化部分可以省略,也可以初始化很多变量。如:for(;i...
    99+
    2018-10-22
    java教程 java for
  • Windows下Emacs中的zsh Shell怎么理解
    本篇文章为大家展示了Windows下Emacs中的zsh Shell怎么理解,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。运行跨平台 shell(例如 Bash 或 zsh)的***优势在于你能在多...
    99+
    2023-06-16
  • Java中的泛型怎么理解
    本篇内容介绍了“Java中的泛型怎么理解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!泛型:是JDK5中引入的特性,可以在编译阶段约束操作的...
    99+
    2023-06-30
  • 怎么理解Java中Linq4j
    这篇文章给大家介绍怎么理解Java中Linq4j,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。开发JAVA一段时间,面临的一大问题就是集合操作,习惯了LINQ的简洁语法,对JAVA的集合操作实在是无甚好感,只能通过C系...
    99+
    2023-06-17
  • Java中怎么理解JNI原理
    这篇文章主要讲解了“Java中怎么理解JNI原理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中怎么理解JNI原理”吧!实例:环境说明:ubuntu 10.4.2 LTS系统程序清单...
    99+
    2023-06-17
  • 怎么理解java中的Exception和Error
    这篇文章主要介绍“怎么理解java中的Exception和Error”,在日常操作中,相信很多人在怎么理解java中的Exception和Error问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解jav...
    99+
    2023-06-16
  • Linux下的权限管理怎么理解
    Linux下的权限管理怎么理解,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Linux下一个文件一经创建,就具有三种访问方式1.读,可以显示该文件的内容2.写,...
    99+
    2023-06-28
  • java的this怎么理解
    java提供了一个this关键字,this关键字总是指向调用该方法的对象。根据this出现位置的不同,this作为对象的默认引用有两种情形。 (推荐学习:java课程)a)、构造器中引用该构造器正在初始化的对象。(...
    99+
    2017-10-14
    java入门 java
  • 怎么理解Oracle中GRID下root.sh脚本
    这篇文章主要介绍“怎么理解Oracle中GRID下root.sh脚本”,在日常操作中,相信很多人在怎么理解Oracle中GRID下root.sh脚本问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方...
    99+
    2022-10-18
  • java中RMI模式怎么理解
    小编给大家分享一下java中RMI模式怎么理解,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、说明是分布式对象的应用,使用RMI技术可以使JVM中的对象调用另一...
    99+
    2023-06-15
  • java中怎么理解Callable接口
    本篇内容介绍了“java中怎么理解Callable接口”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Callable、Executor 与 ...
    99+
    2023-06-16
  • linux环境下java中文乱码怎么解决
    部署在linux下的java应用程序中的中文会变成一个一个的“口”字,也就是乱码问题分析:代码中使用了如下的实现方式:new java.awt.Font("宋体", Font.PLAIN, 12)那么jdk中一定需要“宋体”这个字体($JA...
    99+
    2015-09-26
    linux java
  • Java的代理模式怎么理解
    这篇文章主要介绍“Java的代理模式怎么理解”,在日常操作中,相信很多人在Java的代理模式怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java的代理模式怎么理解”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-29
  • 怎么理解Java中的逆变与协变
    这篇文章主要介绍“怎么理解Java中的逆变与协变”,在日常操作中,相信很多人在怎么理解Java中的逆变与协变问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Java中的逆变与协变”的疑惑有所帮助!接下来...
    99+
    2023-06-02
  • Java 多线程中的Thread该怎么理解
    这篇文章给大家介绍Java 多线程中的Thread该怎么理解,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。package com.thread;public class TestThrea...
    99+
    2023-06-02
  • 怎样理解Java中的多态
    今天就跟大家聊聊有关怎样理解Java中的多态,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、多态的概念       继承关系使一个子类能继承...
    99+
    2023-06-22
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作