zoukankan      html  css  js  c++  java
  • java CopyOnWriteArrayList

    CopyOnWriteArrayList这是一个ArrayList的线程安全的变体,其原理大概可以通俗的理解为:初始化的时候只有一个容器,多个线程同时读取数据没有问题,但是后来有人往里面增加了一个数据,这个时候CopyOnWriteArrayList 底层实现添加的原理是先copy出一个容器(可以简称副本),再往新的容器里添加这个新的数据,最后把新的容器的引用地址赋值给了之前那个旧的的容器地址,但是在添加这个数据的期间,其他线程如果要去读取数据,仍然是读取到旧的容器里的数据。

    package com.hts;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ListConcurrentTest {
        private static final int THREAD_POOL_MAX_NUM = 10;
        private CopyOnWriteArrayList<String> mList = new CopyOnWriteArrayList<String>();
        public static void main(String args[]){
            new ListConcurrentTest().start();
        }
        private void initData() {
            for(int i = 0 ; i <= THREAD_POOL_MAX_NUM ; i ++){
                this.mList.add("...... Line "+(i+1)+" ......");
            }
        }
        private void start(){
            initData();
            ExecutorService service = Executors.newFixedThreadPool(THREAD_POOL_MAX_NUM);
            for(int i = 0 ; i < THREAD_POOL_MAX_NUM ; i ++){
                service.execute(new ListReader(this.mList));
                service.execute(new ListWriter(this.mList,i));
            }
            service.shutdown();
        }
        private class ListReader implements Runnable{
            private List<String> mList ;
            public  ListReader(List<String> list) {
                this.mList = list;
            }
            @Override
            public void run() {
                if(this.mList!=null){
                    for(String str : this.mList){
                        System.out.println(Thread.currentThread().getName()+" : "+ str);
                    }
                }
            }
        }
        private class ListWriter implements Runnable{
            private List<String> mList ;
            private int mIndex;
            public  ListWriter(List<String> list,int index) {
                this.mList = list;
                this.mIndex = index;
            }
            @Override
            public void run() {
                if(this.mList!=null){
                    //this.mList.remove(this.mIndex);
                    this.mList.add("...... add "+mIndex +" ......");
                }
            }
        }
    }
    
    

    如果使用ArrayList 会报错,在同一时间多个线程对同一个List进行读取和增删,会抛出并发异常,如果使用CopyOnWriteArrayList可以解决。
    CopyOnWriteArrayList可以解决并发引起的问题,但是在复制过程中产生另一块内存,资源消耗大。

    转载:原文出处

  • 相关阅读:
    Cocoa中对日期和时间的处理 NSCalendar (一)
    iOS优秀博客收录
    八大排序(内容是转载链接)
    IOS8定位无效问题
    ios 里如何判断当前应用的定位服务是否可用
    MKMapView和MKMapViewDelegate
    根据经纬度翻译成详细位置的各种方法
    iOS 根据经纬度反查 地名
    MapKit学习笔记
    解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated
  • 原文地址:https://www.cnblogs.com/hts-technology/p/9300677.html
Copyright © 2011-2022 走看看