我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JAVA数据结构篇--13线程安全的Set 集合

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JAVA数据结构篇--13线程安全的Set 集合

前言:java 中用于存放不重复元素的set 集合,其中无序的HashSet,以及有序的LinkedHashSet和TreeSet 都是非线程安全的,那么多线程环境下,我们要存放不重复的元素,需要使用哪种集合进行数据存取;

1 使用:

 Set set = Collections.synchronizedSet(new LinkedHashSet<>(10, 0.75f)); CopyOnWriteArraySet copyOnWriteArraySet = new CopyOnWriteArraySet<>(); Set setFromMap = Collections.newSetFromMap(new ConcurrentHashMap<>()); User userOne = new User(); userOne.setId(1).setName("lisi").setAge(20); set.add(userOne); copyOnWriteArraySet.add(userOne); setFromMap.add(userOne); User userTwo = new User(); userTwo.setId(2).setName("wangwu").setAge(20); set.add(userTwo); copyOnWriteArraySet.add(userTwo); setFromMap.add(userTwo); set.remove(userTwo); Iterator iterator1 = set.iterator(); while (iterator1.hasNext()) {     User user = (User) iterator1.next();     System.out.println("user = " + user); }

2 过程:
2.1 放入获取元素:
Collections.synchronizedSet:通过使用synchronized 关键字修饰达到线程安全的目的

public Iterator iterator() {     return c.iterator(); // Must be manually synched by user! } public boolean add(E e) {     synchronized (mutex) {return c.add(e);} } public boolean remove(Object o) {     synchronized (mutex) {return c.remove(o);} }

CopyOnWriteArraySet<>():通过CopyOnWriteArrayList实现,也即底层数据结构使用的数组

private final CopyOnWriteArrayList al;  public CopyOnWriteArraySet() {     al = new CopyOnWriteArrayList(); }public boolean add(E e) {// 当元素不存在的时候添加元素    return al.addIfAbsent(e);}publicboolean addIfAbsent(E e) {   Object[] snapshot = getArray();   return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :       addIfAbsent(e, snapshot);}private boolean addIfAbsent(E e, Object[] snapshot) {   final ReentrantLock lock = this.lock;   // 获取锁   lock.lock();   try {       Object[] current = getArray();       int len = current.length;       if (snapshot != current) {// 当前的数组长度不等于传入进来的数组长度           // Optimize for lost race to another addXXX operation           // 从现有数组中判断要存入的e元素是否已经存在,存在直接返回false           int common = Math.min(snapshot.length, len);           for (int i = 0; i < common; i++)               if (current[i] != snapshot[i] && eq(e, current[i]))                   return false;           if (indexOf(e, current, common, len) >= 0)                   return false;       }       // 数组赋值       Object[] newElements = Arrays.copyOf(current, len + 1);       newElements[len] = e;       setArray(newElements);       return true;   } finally {   //  释放锁       lock.unlock();   }}// 移除元素public boolean remove(Object o) {    Object[] snapshot = getArray();    // 元素存在则进行移除否则直接返回    int index = indexOf(o, snapshot, 0, snapshot.length);    return (index < 0) ? false : remove(o, snapshot, index);} private boolean remove(Object o, Object[] snapshot, int index) {    final ReentrantLock lock = this.lock;    lock.lock();// 获取锁    try {        Object[] current = getArray();        int len = current.length;        //  a: { break a; } 语法将a:之后的代码成为一个方法体,遇到 break跳出方法体        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;        }        // 数组长度-1        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();    }}// 元素遍历:public Iterator iterator() {    return al.iterator();}// CopyOnWriteArrayList 下iteratorpublic Iterator iterator() {    return new COWIterator(getArray(), 0);}private COWIterator(Object[] elements, int initialCursor) {    cursor = initialCursor;    snapshot = elements;}public boolean hasNext() {    return cursor < snapshot.length;}public boolean hasPrevious() {    return cursor > 0;}@SuppressWarnings("unchecked")public E next() {    if (! hasNext())        throw new NoSuchElementException();    return (E) snapshot[cursor++];}

Collections.newSetFromMap(new ConcurrentHashMap<>()):使用ConcurrentHashMap实现元素的存取:

public static  Set newSetFromMap(Map map) {    return new SetFromMap<>(map);}private final Map m;  // The backing mapprivate transient Set s;       // Its keySetSetFromMap(Map map) {    if (!map.isEmpty())        throw new IllegalArgumentException("Map is non-empty");    m = map;    s = map.keySet();}public boolean remove(Object o)   { return m.remove(o) != null; }public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }public Iterator iterator()     { return s.iterator(); }

3 总结:
3.1 Collections.synchronizedSet() 工具类通过对方法增加synchronized 关键字修饰达到线程安全的目的;CopyOnWriteArraySet 通过ReentrantLock 获取和释放锁达到线程安全的目的;Collections.newSetFromMap(new ConcurrentHashMap<>()) 借用ConcurrentHashMap 线程安全的Map集合达到线程安全的目的;
3.2 Collections.synchronizedSet() 工具类直接使用synchronized,并发情况下性能较差;CopyOnWriteArraySet 借助CopyOnWriteArrayList 使用ReentrantLock 性能好一些,但是底层使用了数组,占用内存较多;Collections.newSetFromMap(new ConcurrentHashMap<>()) 通过ConcurrentHashMap性能较好;

来源地址:https://blog.csdn.net/l123lgx/article/details/128504721

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JAVA数据结构篇--13线程安全的Set 集合

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

下载Word文档

猜你喜欢

JAVA数据结构篇--13线程安全的Set 集合

前言:java 中用于存放不重复元素的set 集合,其中无序的HashSet,以及有序的LinkedHashSet和TreeSet 都是非线程安全的,那么多线程环境下,我们要存放不重复的元素,需要使用哪种集合进行数据存取; 1 使用: S
2023-08-17

Golang函数并发编程中数据结构的线程安全性

在 golang 中确保数据结构的线程安全性至关重要。可以使用以下方法:互斥锁:保证同一时刻只有一个 goroutine 访问共享数据。读写锁:允许并发读取,但只能同时执行一个写入。通道:保证发送和接收数据是原子的操作。原子操作:直接操作内
Golang函数并发编程中数据结构的线程安全性
2024-04-17

如何在 C++ 函数中实现线程安全的数据结构?

如何在 c++++ 函数中实现线程安全的数据结构?使用互斥锁保护临界区(共享数据)。线程安全的动态数组示例:使用互斥锁保护 std::vector 中的数据。实战案例:线程安全的队列,使用互斥锁和条件变量实现消息队列的线程安全。如何在 C+
如何在 C++ 函数中实现线程安全的数据结构?
2024-04-27

C++并发编程:如何进行并发数据结构的线程安全设计?

线程安全并发数据结构设计:实现方式:原子类型和互斥锁原子类型:确保多个访问不可分割,保证数据一致性。互斥锁:限制一次一个线程访问共享数据,防止并发数据损坏。实例:线程安全队列展示了使用互斥锁实现的线程安全数据结构。C++并发编程:线程安全并
C++并发编程:如何进行并发数据结构的线程安全设计?
2024-05-03

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录