当前位置: 首页 > news >正文

温州专业营销网站制作沈阳做公司网站的公司

温州专业营销网站制作,沈阳做公司网站的公司,西安人才网官网,西宁网站建设高端简介 CopyOnWriteArrayList是Java中的一个线程安全的集合类#xff0c;是ArrayList线程安全版本#xff0c;主要通过Copy-On-Write#xff08;写时复制#xff0c;简称COW#xff09;机制来保证线程安全。 Copy-On-Write机制核心思想#xff1a;向一个数组中添加数据时…简介 CopyOnWriteArrayList是Java中的一个线程安全的集合类是ArrayList线程安全版本主要通过Copy-On-Write写时复制简称COW机制来保证线程安全。 Copy-On-Write机制核心思想向一个数组中添加数据时不直接操作原始数组而是拷贝原始数组生成一份原始数组副本将需要添加的数据添加到原始数组副本中操作完成后再用原始数组副本直接替换原始数组从而保证多个线程同时操作原始数组时的线程安全。 应用场景 CopyOnWriteArrayList的主要应用场景 读多写少的场景CopyOnWriteArrayList允许多个线程同时对数据进行读操作但同一时刻只允许一个线程对数据进行写操作并且进行写操作时需要复制原始数据的副本造成空间和时间的浪费。允许读写数据时出现短暂不一致的场景CopyOnWriteArrayList写操作完成后需要使用更新后的数据副本替换原始数据有可能使CopyOnWriteArrayList中的数据出现短暂不一致。 实现原理 CopyOnWriteArrayList类的继承关系 Iterable接口CopyOnWriteArrayList类实现了Iterable接口使得它可以被迭代遍历。通过实现iterator()方法可以获取一个迭代器用于遍历集合中的元素。 Collection接口CopyOnWriteArrayList类继承了AbstractCollection类间接实现了Collection接口。通过实现Collection接口CopyOnWriteArrayList类获得了一些常用的集合操作方法比如判断是否包含某个元素、计算集合的大小等。 List接口CopyOnWriteArrayList类间接实现了List接口通过继承AbstractList类实现了List接口的一些方法。List接口定义了有序的集合CopyOnWriteArrayList类通过继承List接口可以按照索引进行访问和操作集合中的元素。 Cloneable接口CopyOnWriteArrayList类实现了Cloneable接口使得它可以进行克隆操作。通过实现clone()方法可以创建CopyOnWriteArrayList对象的副本。 Serializable接口CopyOnWriteArrayList类实现了Serializable接口使得它可以进行序列化操作。通过实现writeObject()和readObject()方法可以将CopyOnWriteArrayList对象转换为字节流并进行存储或传输。 RandomAccess接口CopyOnWriteArrayList类实现了RandomAccess接口表示它可以高效地随机访问元素。RandomAccess接口是一个标记接口用于标识实现该接口的类可以通过索引进行快速随机访问CopyOnWriteArrayList类通过实现该接口表明它可以高效地随机访问元素。 重要属性 CopyOnWriteArrayList类中有两个重要的属性 arrayObject数组用于存储CopyOnWriteArrayList中的数据。该属性使用transient和volatile关键字进行修饰 transient表示序列化CopyOnWriteArrayList对象时array属性不会被自动序列化。 volatile表示一个线程对CopyOnWriteArrayList数据的更新操作对其他线程可见。 lockReentrantLock锁用于保证多个线程同时对CopyOnWriteArrayList进行写操作的线程安全性。该属性也使用transient关键字进行修饰。 CopyOnWriteArrayList类定义代码如下 public class CopyOnWriteArrayListE implements ListE, RandomAccess, Cloneable, java.io.Serializable {...// ReentrantLock锁final transient ReentrantLock lock new ReentrantLock();// Object数组private transient volatile Object[] array;... }构造函数 CopyOnWriteArrayList的构造函数 /*** 无参构造函数*/ public CopyOnWriteArrayList() {// 创建Object数组setArray(new Object[0]); } /*** 有参构造函数* c集合*/ public CopyOnWriteArrayList(Collection? extends E c) {Object[] elements;// 如果参数c为CopyOnWriteArrayList对象则将c中的数组直接赋值给elements数组if (c.getClass() CopyOnWriteArrayList.class)elements ((CopyOnWriteArrayList?)c).getArray();else {// 将参数c转换为数组并赋值给elements数组elements c.toArray();// c.toArray might (incorrectly) not return Object[] (see 6260652)// 如果数组c的类型不是Object[]则将数组c中的元素复制给Object数组再将Object数组赋值给elements数组if (elements.getClass() ! Object[].class)elements Arrays.copyOf(elements, elements.length, Object[].class);}// 将CopyOnWriteArrayList的array属性指向elements数组setArray(elements); } /*** 有参构造函数* toCopyIn数组*/ public CopyOnWriteArrayList(E[] toCopyIn) {// 将数组toCopyIn中的元素复制给Object数组再将Object数组赋值给CopyOnWriteArrayList的array数组setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class)); }核心方法 添加元素-add方法 CopyOnWriteArrayList通过CopyOnWriteArrayList#add方法向其中添加元素。 添加元素执行流程如图所示 处理流程 1线程获得ReentrantLock锁拷贝原始数组array属性对应的数组生成原始数组副本数组长度为原始数组的长度1。2向原始数组副本中添加元素。3将CopyOnWriteArrayList中的array属性值替换为原始数组副本线程释放ReentrantLock锁。 CopyOnWriteArrayList#add(E e)方法源码解析 /*** 向数组中末尾位置添加元素* e待添加的元素*/ public boolean add(E e) {final ReentrantLock lock this.lock;// 加锁lock.lock();try {// 获取原始数组array属性对应的数组Object[] elements getArray();int len elements.length;// 拷贝原始数组生成原始数组副本数组长度为原始数组的长度1Object[] newElements Arrays.copyOf(elements, len 1);// 向原始数组副本中添加元素newElements[len] e;// 将CopyOnWriteArrayList中的array属性值替换为原始数组副本setArray(newElements);return true;} finally {// 释放锁lock.unlock();} }CopyOnWriteArrayList#add(int index, E element)方法源码解析 /*** 向数组中指定位置添加元素* index数组下标* element待添加的元素*/ public void add(int index, E element) {final ReentrantLock lock this.lock;// 加锁lock.lock();try {// 获取原始数组Object[] elements getArray();int len elements.length;// 数组下标超过数组长度或数组下标小于0抛出数组越界异常if (index len || index 0)throw new IndexOutOfBoundsException(Index: index, Size: len);Object[] newElements;int numMoved len - index;// 在原始数组末尾插入元素if (numMoved 0)// 拷贝原始数组生成原始数组副本数组长度为原始数组的长度1newElements Arrays.copyOf(elements, len 1);else {// 在原始数组中间插入元素创建新数组数组长度为原始数组的长度1newElements new Object[len 1];// 拷贝原始数组中index下标之前的元素到新数组中System.arraycopy(elements, 0, newElements, 0, index);// 拷贝原始数组中index下标之后的元素到新数组中注意此部分元素从index位置开始向后移动一位System.arraycopy(elements, index, newElements, index 1,numMoved);}// 向原始数组副本中添加元素newElements[index] element;// 将CopyOnWriteArrayList中的array属性值替换为原始数组副本setArray(newElements);} finally {lock.unlock();} }删除元素-remove方法 CopyOnWriteArrayList通过CopyOnWriteArrayList#remove方法删除指定位置的元素。 CopyOnWriteArrayList#remove方法源码解析 public E remove(int index) {final ReentrantLock lock this.lock;// 加锁lock.lock();try {// 获取原始数组Object[] elements getArray();int len elements.length;// 获取原始数组中index下标对应的元素E oldValue get(elements, index);int numMoved len - index - 1;// 删除原始数组末尾元素if (numMoved 0)// 将CopyOnWriteArrayList的array属性重新指向删除指定位置元素之后的原始数组副本setArray(Arrays.copyOf(elements, len - 1));else {// 删除原始数组中间元素创建新数组数组长度为原始数组的长度-1Object[] newElements new Object[len - 1];// 拷贝原始数组中index下标前面的元素到新数组中System.arraycopy(elements, 0, newElements, 0, index);// 拷贝原始数组中index下标后面的元素到新数组中注意此部分元素从index1位置开始向前移动一位System.arraycopy(elements, index 1, newElements, index,numMoved);// 将CopyOnWriteArrayList中的array属性值替换为原始数组副本setArray(newElements);}return oldValue;} finally {// 释放锁lock.unlock();} }更新元素-set方法 CopyOnWriteArrayList通过CopyOnWriteArrayList#set方法更新指定位置的元素。 CopyOnWriteArrayList#set方法源码解析 public E set(int index, E element) {final ReentrantLock lock this.lock;// 加锁lock.lock();try {// 获取原始数组Object[] elements getArray();// 获取原始数组中index下标对应的元素E oldValue get(elements, index);// 如果旧值与新值不相等则用新值替换旧值if (oldValue ! element) {int len elements.length;Object[] newElements Arrays.copyOf(elements, len);// 新值覆盖旧值newElements[index] element;setArray(newElements);} else {// Not quite a no-op; ensures volatile write semanticssetArray(elements);}//返回旧值return oldValue;} finally {// 释放锁lock.unlock();} }获取元素-get方法 CopyOnWriteArrayList通过CopyOnWriteArrayList#get方法获取指定位置的元素。 CopyOnWriteArrayList#get方法源码解析 /*** 获取指定位置的元素* index数组下标*/ public E get(int index) {// 返回array数组中指定下标对应的元素return get(getArray(), index); } private E get(Object[] a, int index) {return (E) a[index]; }遍历元素-iterator方法 CopyOnWriteArrayList可以通过CopyOnWriteArrayList#iterator方法进行遍历。在调用CopyOnWriteArrayList#iterator方法时会创建一个COWIterator迭代器创建COWIterator迭代器时传入的是array数组的快照并初始化一个游标通过游标遍历array数组快照中的所有元素。 CopyOnWriteArrayList#iterator方法源码解析 // 迭代方法 public IteratorE iterator() {// 通过COWIterator迭代器遍历array数组return new COWIteratorE(getArray(), 0); } // COWIterator迭代器 static final class COWIteratorE implements ListIteratorE {// 保存array数组快照private final Object[] snapshot;// 游标private int cursor;private COWIterator(Object[] elements, int initialCursor) {cursor initialCursor;snapshot elements;}...// 删除public void remove() {throw new UnsupportedOperationException();}// 修改public void set(E e) {throw new UnsupportedOperationException();}// 新增public void add(E e) {throw new UnsupportedOperationException();}... }其中COWIterator迭代器遍历的是array数组快照因此对array数组快照进行增删改操作时会抛出 UnsupportedOperationException异常。 使用示例 /*** author 南秋同学* CopyOnWriteArrayList使用示例*/ Slf4j public class CopyOnWriteArrayListExample {private static CopyOnWriteArrayListString list new CopyOnWriteArrayList();SneakyThrowspublic static void main(String[] args) {// 创建新增元素线程Thread thread1 new Thread(new Runnable() {SneakyThrowsOverridepublic void run() {for (int i 0; i 8; i) {list.add(element- i);log.info(添加元素 element-{}, i);Thread.sleep(100);}}});// 创建删除元素线程Thread thread2 new Thread(new Runnable() {SneakyThrowsOverridepublic void run() {for (int i 0; i 5; i) {if(list.size() 0){list.remove(0);log.info(删除元素----- element-{}, i);}Thread.sleep(200);}}});thread1.start();thread2.start();thread1.join();thread2.join();log.info(list中的最终元素{}, list);// 遍历元素for (String element: list){log.info(打印元素{}, element);}} }执行结果 23:03:24.187 [Thread-0] - 添加元素 element-0 23:03:24.187 [Thread-1] - 删除元素----- element-0 23:03:24.296 [Thread-0] - 添加元素 element-1 23:03:24.397 [Thread-1] - 删除元素----- element-1 23:03:24.397 [Thread-0] - 添加元素 element-2 23:03:24.498 [Thread-0] - 添加元素 element-3 23:03:24.600 [Thread-1] - 删除元素----- element-2 23:03:24.600 [Thread-0] - 添加元素 element-4 23:03:24.703 [Thread-0] - 添加元素 element-5 23:03:24.805 [Thread-1] - 删除元素----- element-3 23:03:24.807 [Thread-0] - 添加元素 element-6 23:03:24.909 [Thread-0] - 添加元素 element-7 23:03:25.007 [Thread-1] - 删除元素----- element-4 23:03:25.211 [main] - list中的最终元素[element-5, element-6, element-7] 23:03:25.212 [main] - 打印元素element-5 23:03:25.212 [main] - 打印元素element-6 23:03:25.212 [main] - 打印元素element-7从执行结果可以看出多个线程同时对CopyOnWriteArrayList进行写操作时可以保证线程安全。
http://www.zqtcl.cn/news/41344/

相关文章:

  • 郑州做网站的多不多网站建设原型
  • 做网站 属于电子商务wordpress网站会员太多
  • 做算命网站挣钱么中国建设银行登录
  • 宝安区城市建设局网站友链交换网站源码
  • 怎么查询网站是否被收录制作网站的公司做网站去哪里找
  • 门户网站建设注意问题合肥网站维护公司
  • 宜昌市住房和城乡建设厅网站vps 可以做多个网站吗
  • 一帘幽梦紫菱做的网站做网站可以挣多少钱
  • 临淄网站建设成品短视频代码推荐大全
  • 怎样在微信里做网站阿里指数网站
  • 做计算机题目的网站公司做网站的作用
  • 石家庄哪里做微网站六安招聘网最新招聘
  • 云霄县建设局网站投诉怎么在本地安装网站
  • 有没有专业做电视测评的网站电子商务前景怎么样
  • 泉州网站建设技术公司企业门户网站建设方案后台管理
  • 网站建设推广平台网址深圳专业网站设计怎么做
  • 类似淘宝的网站怎么做的做一张网页需要多少钱
  • 绞铜机 东莞网站建设wordpress 文章采集
  • 常用网站开发工具促销活动推广语言
  • 农村建设自己的网站wordpress采集教程
  • 浙江制造品牌建设网站it软件外包公司
  • 家居装修企业网站源码成都网站建设常凡云
  • 做营销型网站的教程页面设计叫什么
  • 中小型企业网站大全西安平面设计培训学校哪个好
  • 做网站号码厦门建行网站首页
  • 网站开发 c俄罗斯网站域名注册
  • 二级域名网站建设规范网络营销失败案例及分析
  • wordpress网站在线安装十大免费软件不收费安卓
  • 情侣博客网站模板网页设计与制作期末考试试题及答案
  • 创一个网站怎样赚钱手机免费网站