Java中线程安全的List_java 静态一个 线程安全list-程序员宅基地

技术标签: Java技术  Java  线程安全  List  

简单说一下java中线程安全的List 

一、Vector

Vector是大家熟知的线程安全的List集合,不过他的性能是最差,所有的方法都是加了synchronized来同步,从而保证线程安全。

源码也是使用数组来存储数据,有以下构造方法。 

      /**
     * Constructs an empty vector with the specified initial capacity and
     * capacity increment.
     *
     * @param   initialCapacity     the initial capacity of the vector
     * @param   capacityIncrement   the amount by which the capacity is
     *                              increased when the vector overflows
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

    /**
     * Constructs an empty vector with the specified initial capacity and
     * with its capacity increment equal to zero.
     *
     * @param   initialCapacity   the initial capacity of the vector
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

    /**
     * Constructs an empty vector so that its internal data array
     * has size {@code 10} and its standard capacity increment is
     * zero.
     */
    public Vector() {
        this(10);
    }

    /**
     * Constructs a vector containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this
     *       vector
     * @throws NullPointerException if the specified collection is null
     * @since   1.2
     */
    public Vector(Collection<? extends E> c) {
        elementData = c.toArray();
        elementCount = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }

它的增加、修改、获取、删除等都通过synchronized来同步。

 public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        ensureCapacityHelper(elementCount + 1);
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }
 public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }
 public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }
public synchronized void removeAllElements() {
        modCount++;
        // Let gc do its work
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;

        elementCount = 0;
    }
public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }
 public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
 public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

二、Collections.SynchronizedList

SynchronizedList是Collections类的静态内部类,它能把所有 List 接口的实现类转换成线程安全的List,比 Vector 有更好的扩展性和兼容性。

SynchronizedList的构造方法如下:

        SynchronizedList(List<E> list) {
            super(list);
            this.list = list;
        }
        SynchronizedList(List<E> list, Object mutex) {
            super(list, mutex);
            this.list = list;
        }

SynchronizedList的部分方法源码如下:

public boolean equals(Object o) {
            if (this == o)
                return true;
            synchronized (mutex) {return list.equals(o);}
        }
        public int hashCode() {
            synchronized (mutex) {return list.hashCode();}
        }

        public E get(int index) {
            synchronized (mutex) {return list.get(index);}
        }
        public E set(int index, E element) {
            synchronized (mutex) {return list.set(index, element);}
        }
        public void add(int index, E element) {
            synchronized (mutex) {list.add(index, element);}
        }
        public E remove(int index) {
            synchronized (mutex) {return list.remove(index);}
        }

        public int indexOf(Object o) {
            synchronized (mutex) {return list.indexOf(o);}
        }
        public int lastIndexOf(Object o) {
            synchronized (mutex) {return list.lastIndexOf(o);}
        }

        public boolean addAll(int index, Collection<? extends E> c) {
            synchronized (mutex) {return list.addAll(index, c);}
        }

        public ListIterator<E> listIterator() {
            return list.listIterator(); // Must be manually synched by user
        }

        public ListIterator<E> listIterator(int index) {
            return list.listIterator(index); // Must be manually synched by user
        }

        public List<E> subList(int fromIndex, int toIndex) {
            synchronized (mutex) {
                return new SynchronizedList<>(list.subList(fromIndex, toIndex),
                                            mutex);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            synchronized (mutex) {list.replaceAll(operator);}
        }
        @Override
        public void sort(Comparator<? super E> c) {
            synchronized (mutex) {list.sort(c);}
        }

        /**
         * SynchronizedRandomAccessList instances are serialized as
         * SynchronizedList instances to allow them to be deserialized
         * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
         * This method inverts the transformation.  As a beneficial
         * side-effect, it also grafts the RandomAccess marker onto
         * SynchronizedList instances that were serialized in pre-1.4 JREs.
         *
         * Note: Unfortunately, SynchronizedRandomAccessList instances
         * serialized in 1.4.1 and deserialized in 1.4 will become
         * SynchronizedList instances, as this method was missing in 1.4.
         */
        private Object readResolve() {
            return (list instanceof RandomAccess
                    ? new SynchronizedRandomAccessList<>(list)
                    : this);
        }

它所有方法都是带同步对象锁的,和 Vector 一样,它不是性能最优的。

三、CopyOnWriteArrayList

CopyOnWriteArrayList是java1.5以后才加入的新类,从命名可以理解为复制在写入的List。

它的添加时加锁的(ReentrantLock ,非synchronized同步锁),读操作是没有加锁。

添加和删除方法部分代码实现:

 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();
        }
    }
 private boolean remove(Object o, Object[] snapshot, int index) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] current = getArray();
            int len = current.length;
            if (snapshot != current) findIndex: {
                int prefix = Math.min(index, len);
                for (int i = 0; i < prefix; i++) {
                    if (current[i] != snapshot[i] && eq(o, current[i])) {
                        index = i;
                        break findIndex;
                    }
                }
                if (index >= len)
                    return false;
                if (current[index] == o)
                    break findIndex;
                index = indexOf(o, current, index, len);
                if (index < 0)
                    return false;
            }
            Object[] newElements = new Object[len - 1];
            System.arraycopy(current, 0, newElements, 0, index);
            System.arraycopy(current, index + 1,
                             newElements, index,
                             len - index - 1);
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

添加或者删除元素时,先加锁,再进行复制替换操作,最后再释放锁。 

它的优势在于,读操作是不加任和锁。这样做的好处是,在高并发情况下,读取元素时就不用加锁,写数据时才加锁,大大提升了读取性能。

看下它的 get 方法源码:

    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    /**
     * {@inheritDoc}
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        return get(getArray(), index);
    }

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43881309/article/details/101687369

智能推荐

七牛云存储的简单使用总结_7牛 s3存储的使用-程序员宅基地

文章浏览阅读1.1w次。七牛是专注文件存储的第三方服务商,服务较好。自己最近做到服务器存储图片的时候就想到用七牛来做,将图片或者文件存放在七牛,然后自己服务器只存放资源存放在七牛文件的url。今天主要分享两个内容:凭证的获取,安卓上传文件在做之前还是先把官方文档好好读几遍比较好首先说说凭证,七牛对所有上传的资源都需要身份验证,就是通过凭证来验证,验证通过,那么就可以成功上传文件,不通过,七牛服务器会反_7牛 s3存储的使用

Windows10 -64 安装tensorflow遇到的:cuda安装后找不到安装文件目录_没有nvidia gpu computing toolkit文件夹-程序员宅基地

文章浏览阅读3w次,点赞32次,收藏114次。Windows10 -64 安装tensorflow遇到的:cuda安装后找不到安装文件目录目录 一、错误:cuda安装后找不到安装文件目录二、查看cuda驱动程序的版本三、补充内容四、执行测试程序出错五、常用命令总结 一、错误:cuda安装后找不到安装文件目录原因是:将临时解压目录和安装目录设置成一样的了,导致安装结束,临时解压目录被删除,所以安装目录也被删除了;..._没有nvidia gpu computing toolkit文件夹

Memcache内部剖析_memcache 架构分析-程序员宅基地

文章浏览阅读1.1k次。本文主要对memcache内部Big-O、LRU算法、内存分配(Memory allocation)、一致性哈希(Consistent hashing)等进行了深入剖析,并举例生动形象描述了一致性哈希算法_memcache 架构分析

计算机数据分析试题,计算机二级考试真题-Excel-小马-公务员考试成绩数据分析...-程序员宅基地

文章浏览阅读2.1k次。人事部统计员小马负责本次公务员考试成绩数据的整理,按照下列要求帮助小马完成相关的整理、统计和分析工作:1.将考生文件夹下的工作簿文档“Excel素材.xlsx”另存为“Excel.xlsx”(“.xlsx”为文件扩展名),之后所有的操作均基于此文件,否则不得分。操作过程中,不可以随意改变工作表中数据的顺序。2.将考生文件夹下的工作簿“行政区划代码对照表.xlsx”中的工作表“Sheet1”复制到工..._excel准考证号的第四位为1,考试类别为a考试成绩

这个团队10年牺牲1000人,马云远赴非洲为世界上最危险的职业颁奖-程序员宅基地

文章浏览阅读135次。跟你说,昨天......马云远赴非洲为他们颁奖......他们是谁呢?南非当地时间8月7日,来自非洲各国的一线野生动物巡护员齐聚开普敦。马云代表阿里巴巴公益基金会和桃花源生态保护基金会为他们颁奖。这群用生命保护大象、狮子和犀牛的巡护员们,第一次得到来自中国的资金和技术支持。在颁奖现场,每一位嘉宾的座位上都摆着一只可爱的非洲野生动物公仔。它们..._史上最危险的工作但是奖金最多

Winform UI界面设计例程——多线程访问UI控件_winform多线程访问控件-程序员宅基地

文章浏览阅读4k次。这里讨论两种多线程访问UI控件的方法,线程完成后更新Lable控件如下图,第一种方式为方式1按钮按下,线程运行,并更新label第二种方法为按下方式2按钮,线程运行,完成后更新label 新建winform项目程序,布局如上,大家可以不用配色,简单即可引用using System.Threading; 第一种方法:使用delegate和invoke来从其他线程中调用控件 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它,所以我们判断这个属性来更新label的值 _winform多线程访问控件

随便推点

【51单片机】之入门详解(一)_51单片机编程入门基础知识-程序员宅基地

文章浏览阅读1.2k次,点赞21次,收藏19次。【51单片机】之入门详解(一)_51单片机编程入门基础知识

uwsgi的3个容易掉坑的配置(timeout、harakiri、buffer-size)_uwsgi harakiri-程序员宅基地

文章浏览阅读2.9w次,点赞16次,收藏27次。我采用的.ini文件[uwsgi]master = truewsgi-file=myppt/wsgi.pyprocesses = 1threads = 2chdir = /www/wwwroot/ppt_jpg/myppt/http = 127.0.0.1:9876virtualenv=/www/wwwroot/ppt_jpg/myppt/ppt_venvdaemonize=uw..._uwsgi harakiri

ffmpeg5.0+h264+h265 windows下编译方法-程序员宅基地

文章浏览阅读7.4k次,点赞14次,收藏47次。前言: 最近准备在windows上面用ffmpeg做视频编解码工作,找了很多博客对编译方法描述都不全,花了一天时间自己折腾编译通过了,写篇比较完整的博客分享给大家,希望对大家有所帮助,另外,感谢其他博主的分享!一,源码包下载1.ffmpeg下载下载地址:https://ffmpeg.org(1)在主页面中找到ffmpeg5.0版本点击(2)点击下载,这里我下载的是gzip包2,下载x264代码下载地址:x264, the best H.2..._ffmpeg5.0

空洞卷积(膨胀卷积)的相关知识以及使用建议(HDC原则)-程序员宅基地

文章浏览阅读2.1w次,点赞118次,收藏586次。空洞卷积(膨胀卷积)的相关知识以及使用建议(HDC原则)_空洞卷积

python实现对excel数据某列提取文件名,匹配文件夹提取对应文件_利用python从excel表中读取文件名称再去本地提取文件-程序员宅基地

文章浏览阅读1.6k次。python实现对excel数据某列提取文件名,匹配文件夹提取对应文件_利用python从excel表中读取文件名称再去本地提取文件

kmeans聚类算法_机器学习/算法校招面试考点汇总(附面试题和答案)【持续更新】_笔经面经...-程序员宅基地

文章浏览阅读916次。以下不作为机器学习/算法工程师的学习路径,只是汇总的校招机器学习/算法工程师面试考点(因为还有笔试考点,后面结合在一起给大家学习路径),后续会为大家更新10w+字数的机器学习/算法工程师校招面试题库,还有其他岗位的相关题库和资料,想要什么岗位的可以留言哦~ 本篇根据各个公司的面试问的问题的大数据进行总结,后面还会更新面试中考察所占比例,当然,本文只包括技术面,不太包括hr面或者一些其他谈人生理..._sklearn dbscan kmeans isodata