Java的List如何实现线程安全?

Collections.synchronizedList(names);效率最高,线程安全

Java的List是我们平时很常用的集合,线程安全对于高并发的场景也十分的重要,那么List如何才能实现线程安全呢 ?

加锁

首先大家会想到用Vector,这里我们就不讨论了,首先讨论的是加锁,例如下面的代码

public class Synchronized{

private List names = new LinkedList<>();

public synchronized void addName(String name ){

names.add("abc");

}

public String getName(Integer index){

Lock lock =new ReentrantLock();

lock.lock();

try {

return names.get(index);

}catch (Exception e){

e.printStackTrace();

}

finally {

lock.unlock();

}

return null;

}

}

synchronized一加,或者使用lock 可以实现线程安全,但是这样的List要是很多个,代码量会大大增加。

java自带类

在java中我找到自带有两种方法

CopyOnWriteArrayList

CopyOnWrite 写入时复制,它使一个List同步的替代品,通常情况下提供了更好的并发性,并且避免了再迭代时候对容器的加锁和复制。通常更适合用于迭代,在多插入的情况下由于多次的复制性能会一定的下降。

下面是add方法的源代码

public boolean add(E e) {

final ReentrantLock lock = this.lock; // 加锁 只允许获得锁的线程访问

lock.lock();

try {

Object[] elements = getArray();

int len = elements.length;

// 创建个长度加1的数组并复制过去

Object[] newElements = Arrays.copyOf(elements, len + 1);

newElements[len] = e; // 赋值

setArray(newElements); // 设置内部的数组

return true;

} finally {

lock.unlock();

}

}

Collections.synchronizedList

Collections中有许多这个系列的方法例如

主要是利用了装饰者模式对传入的集合进行调用 Collotions中有内部类SynchronizedList

static class SynchronizedList

extends SynchronizedCollection

implements List {

private static final long serialVersionUID = -7754090372962971524L;

final List list;

SynchronizedList(List list) {

super(list);

this.list = list;

}

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);}

}

static class SynchronizedCollection implements Collection, Serializable {

private static final long serialVersionUID = 3053995032091335093L;

final Collection c; // Backing Collection

final Object mutex; // Object on which to synchronize

这里上面的mutex就是锁的对象 在构建时候可以指定锁的对象 主要使用synchronize关键字实现线程安全

/**

* @serial include

*/

static class SynchronizedList

extends SynchronizedCollection

implements List {

private static final long serialVersionUID = -7754090372962971524L;

final List list;

SynchronizedList(List list) {

super(list);

this.list = list;

}

SynchronizedList(List list, Object mutex) {

super(list, mutex);

this.list = list;

}

这里只是列举SynchronizedList ,其他类类似,可以看下源码了解下。

测试

public class Main {

public static void main(String[] args) {

List names = new LinkedList<>();

names.add("sub");

names.add("jobs");

// 同步方法1 内部使用lock

long a = System.currentTimeMillis();

List strings = new CopyOnWriteArrayList<>(names);

for (int i = 0; i < 100000; i++) {

strings.add("param1");

}

long b = System.currentTimeMillis();

// 同步方法2 装饰器模式使用 synchronized

List synchronizedList = Collections.synchronizedList(names);

for (int i = 0; i < 100000; i++) {

synchronizedList.add("param2");

}

long c = System.currentTimeMillis();

System.out.println("CopyOnWriteArrayList time == "+(b-a));

System.out.println("Collections.synchronizedList time == "+(c-b));

}

}

两者内部使用的方法都不一样,CopyOnWriteArrayList内部是使用lock进行加锁解锁完成单线程访问,synchronizedList使用的是synchronize

进行了100000次添加后时间对比如下:

可以看出来还是使用了synchronize的集合工具类在添加方面更加快一些,其他方法这里篇幅关系就不测试了,大家有兴趣去试一下。

————————————————

版权声明:本文为CSDN博主「肉 肉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

java线程安全的list_Java的List如何实现线程安全?相关推荐

  1. java线程安全的list_Java中的集合和线程安全

    通过Java指南我们知道Java集合框架(Collection Framework)如何为并发服务,我们应该如何在单线程和多线程中使用集合(Collection). 话题有点高端,我们不是很好理解.所 ...

  2. java 线程同步的list_java集合框架线程同步代码详解

    List接口的大小可变数组的实现.实现了所有可选列表操作,并允许包括null在内的所有元素.除了实现List接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小.(此类大致上等同于Vector ...

  3. java结束全部操作代码_Java创建与结束线程代码示例

    这篇文章主要介绍了Java创建与结束线程代码示例,小编觉得挺不错的,这里分享给大家,供需要的朋友参考. 本文讲述了在Java中如何创建和结束线程的最基本方法,只针对于Java初学者.一些高级知识如线程 ...

  4. Java一个线程能否结束另一个永不停止的线程

    在Java中停止一个线程有三种办法 : 1.正常结束执行: 2.发生异常; 3.被其他线程stop(Java官方不建议) 参考:https://docs.oracle.com/javase/8/doc ...

  5. java线程间通信管道_通过管道进行线程间通信

    管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据.一个线程发送数据到输出管道,另一个线程从输入管道中读数据.通过管道,实现不同线程间的通信,而无须借助类似共享变量.临时文件之 ...

  6. java 多线程 进程_Java多线程1:进程与线程概述

    进程和线程 谈到多线程,就得先讲进程和线程的概念. 进程 进程可以理解为受操作系统管理的基本运行单元.360浏览器是一个进程.WPS也是一个进程,正在操作系统中运行的".exe"都 ...

  7. 每个java程序都至少有一个线程给主线程,java程序在主线程中判断各个子线程状态的操作,该如何解决...

    java程序在主线程中判断各个子线程状态的操作 每个子线程在队列为空时会wait等待其他线程添加新url到队列,到最后所有子线程都取不到url时也会都wait住,要在主线程中判断如果所有的子线程都是w ...

  8. Java多线程笔记(零):进程、线程与通用概念

    前言 不积跬步,无以至千里:不积小流,无以成江海.在学习Java多线程相关的知识前,我们首先需要去了解一点操作系统的进程.线程以及相关的基础概念. 进程 通常,我们把一个程序的执行称为一个进程.反过来 ...

  9. Java中的“可运行的实现”与“扩展线程”

    从什么时候开始在Java中使用线程开始,我发现了以下两种编写线程的方法: 与implements Runnable : public class MyRunnable implements Runna ...

最新文章

  1. android读取剪切板的方法,Android复制粘贴剪切板内容的一种方法
  2. 反射 Class类和Class实例
  3. jQuery遍历div,判断是否为空,为空时执行某个操作
  4. 空间点过程(Point Processes)和随机测度(Random Measure)
  5. excel中VBa应用总结
  6. For the completeness of the story
  7. crontab使用环境变量
  8. 学校源码php,闪灵CMS学校建站系统(含小程序) v5.0 bulid20200319_php免费源码
  9. html如何让窗口不在任务栏显示,小编教你任务栏不显示打开的窗口怎么解决
  10. BZOJ 1260 paint
  11. 天梯图excl_处理器2014最全天梯图
  12. c语言中的各种变量是如何存储的(-)
  13. 【jquery-跨域】
  14. insmod,rmmod
  15. Idel插件jrebel安装以及破解教程
  16. 昆明拟整治11类陋习 行人翻越隔离设施罚50元
  17. Matlab机器人工具箱
  18. 【Python】先玩个魔术 ,再讲二进制 - 心灵感应魔法
  19. 【Linux操作】使用zip 压缩命令打包程序为.zip压缩包并进行解压缩
  20. 常见音乐文件格式介绍

热门文章

  1. oracle进入asm命令,Oracle常用ASM操作命令
  2. 彻底解决LSASS.exe进程病毒!
  3. linux ssh加固
  4. 大规模MIMO天线技术
  5. 计算机是一种能够预先,第1章计算机基础知识 一级msoffice电子教案
  6. 怎样解决电脑右下角弹出的广告
  7. Win95+VC6+IE4+MSXML3时的XMLHTTP解决方法
  8. 织梦(dedecms)仿站教程第一讲-准备工作
  9. ECSHOP通过改变模板路径制作手机站
  10. 社区卫生医疗信息平台