并发情况下 Set 的使用——深入理解 Collections.synchronizedSet 的用法

引言

在 Java 开发中,我们经常需要在多线程环境下操作集合,比如 Set。为了确保线程安全,Java 提供了多种工具和类,Collections.synchronizedSet 是其中一种简单有效的解决方案。本文将围绕 Collections.synchronizedSet 的使用场景、工作原理以及注意事项展开详细讲解。


什么是 Collections.synchronizedSet

Collections.synchronizedSet 是 Java 提供的一种工具方法,用于将普通的 Set 包装成线程安全的集合。它通过同步对 Set 的操作来确保多个线程同时访问时不会出现数据不一致的问题。

它属于 java.util.Collections 类的一部分,方法签名如下:

public static <T> Set<T> synchronizedSet(Set<T> s)

示例代码

Set<String> stationIdSet = new HashSet<>();
Set<String> synchronizedSet = Collections.synchronizedSet(stationIdSet);

这里,synchronizedSet 是一个线程安全的集合,所有对其的操作都会被自动同步。


使用场景

  1. 多线程环境
    当多个线程需要共享一个 Set 时,为了避免竞争条件导致的数据不一致,可以使用 synchronizedSet

  2. 无需更复杂的同步逻辑
    对于简单的场景,比如添加、删除元素,synchronizedSet 提供了开箱即用的线程安全性。

  3. 集合的线程安全包装
    如果不想直接使用 ConcurrentHashMap 或其他并发集合,synchronizedSet 是一个轻量级的选择。


工作原理

Collections.synchronizedSet 的核心是通过内部锁实现的。每次对集合的操作都会被同步到同一个锁上,确保线程安全。例如:

public static <T> Set<T> synchronizedSet(Set<T> s) {return new SynchronizedSet<>(s);
}private static class SynchronizedSet<E> implements Set<E>, Serializable {private final Set<E> s;final Object mutex; // 同步锁SynchronizedSet(Set<E> s) {this.s = Objects.requireNonNull(s);this.mutex = this;}public synchronized boolean add(E e) {synchronized (mutex) {return s.add(e);}}// 其他方法类似
}

可以看到,每个操作都通过一个内部锁(mutex)来同步。


示例代码

以下代码展示了 Collections.synchronizedSet 的基本使用。

代码示例

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;public class SynchronizedSetExample {public static void main(String[] args) {// 原始 SetSet<String> stationIdSet = new HashSet<>();// 包装为线程安全的 SetSet<String> synchronizedSet = Collections.synchronizedSet(stationIdSet);// 启动多个线程并发操作集合Runnable task = () -> {for (int i = 0; i < 5; i++) {synchronizedSet.add(Thread.currentThread().getName() + "-" + i);}};Thread t1 = new Thread(task, "Thread-1");Thread t2 = new Thread(task, "Thread-2");t1.start();t2.start();// 等待线程完成try {t1.join();t2.join();} catch (InterruptedException e) {e.printStackTrace();}// 遍历集合(需要外部同步)synchronized (synchronizedSet) {System.out.println("最终集合内容: " + synchronizedSet);}}
}

示例输出

最终集合内容: [Thread-1-0, Thread-1-1, Thread-1-2, Thread-2-0, Thread-2-1, Thread-2-2]

注意事项

  1. 外部同步
    遍历 synchronizedSet 时,仍然需要手动同步,以防止并发修改引发异常。例如:

    synchronized (synchronizedSet) {for (String id : synchronizedSet) {System.out.println(id);}
    }
    
  2. 性能问题
    synchronizedSet 是基于锁实现的,在高并发场景下,性能可能不如 ConcurrentSkipListSet 或其他并发集合。

  3. 适用场景
    对于频繁读写的场景,建议使用 ConcurrentHashMapCopyOnWriteArraySet


与其他线程安全集合的对比

集合类型线程安全性实现方式适用场景
Collections.synchronizedSet通过锁同步简单操作,低并发场景
ConcurrentSkipListSet基于跳表实现高并发读写
CopyOnWriteArraySet通过复制实现读多写少,数据量较小时

总结

Collections.synchronizedSet 是一个方便的工具,可以轻松地将普通集合转换为线程安全的集合。它适用于简单的多线程操作,但在高并发场景下,性能可能会成为瓶颈。因此,在选择线程安全集合时,应根据具体场景选择合适的工具。

你学会了吗?如果本文对你有帮助,请点赞、评论支持!😊


相关参考

  • Java 官方文档
  • Java 并发集合详解

期待你的建议和反馈!如果你有其他问题或想法,欢迎在评论区交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/479338.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件上传upload-labs-docker通关

&#xff08;图片加载不出&#xff0c;说明被和谐了&#xff09; 项目一&#xff1a; sqlsec/ggctf-upload - Docker Image | Docker Hub 学习过程中,可以对照源码进行白盒分析. 补充&#xff1a;环境搭建在Linux虚拟机上的同时&#xff0c;以另一台Windows虚拟机进行测试最…

【Android】静态广播接收不到问题分析思路

参考资料&#xff1a; Android 静态广播注册流程(广播2)-CSDN博客 Android广播发送流程(广播3)_android 发送广播-CSDN博客 https://zhuanlan.zhihu.com/p/347227068 在Android中&#xff0c;静态广播如果静态广播不能接收&#xff0c;我们可以从整个流程中去分析&#xff…

2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略(详细解题思路)

在当下&#xff0c; 日益发展的时代&#xff0c;宠物的数量应该均为稳步上升&#xff0c;在美国出现了下降的趋势&#xff0c; 中国 2019-2020 年也下降&#xff0c;这部分变化可能与疫情相关。需要对该部分进行必要的解释说明。 问题 1: 基于附件 1 中的数据及您的团队收集的额…

Git简单介绍

一、 Git介绍与安装 1.1 Git简介 Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 1.2集中式(SVN&#xff09; VS 分布式(git) 集中式版本控制系统&#xff0c;版本库是集中存放在中央服务器的&#xff0c;工作时要先从中央…

CSS之3D转换

三维坐标系 三维坐标系其实就是指立体空间&#xff0c;立体空间是由3个轴共同组成的。 x轴:水平向右注意:x右边是正值&#xff0c;左边是负值 y轴:垂直向下注意:y下面是正值&#xff0c;上面是负值 z轴:垂直屏幕注意:往外面是正值&#xff0c;往里面是负值 3D移动 translat…

kafka生产者和消费者命令的使用

kafka-console-producer.sh 生产数据 # 发送信息 指定topic即可 kafka-console-producer.sh \ --bootstrap-server bigdata01:9092 \ --topic topicA # 主题# 进程 29124 ConsoleProducer kafka-console-consumer.sh 消费数据 # 消费数据 kafka-console-consumer.sh \ --boo…

基于Springboot的心灵治愈交流平台系统的设计与实现

基于Springboot的心灵治愈交流平台系统 介绍 基于Springboot的心灵治愈交流平台系统&#xff0c;后端框架使用Springboot和mybatis&#xff0c;前端框架使用Vuehrml&#xff0c;数据库使用mysql&#xff0c;使用B/S架构实现前台用户系统和后台管理员系统&#xff0c;和不同级别…

【人工智能】Python常用库-Scikit-learn常用方法教程

Scikit-learn 是一个功能强大的机器学习库&#xff0c;支持数据预处理、分类、回归、聚类、降维等功能&#xff0c;广泛用于模型开发与评估。以下是 Scikit-learn 的常用方法及详细说明。 1. 安装与导入 安装 Scikit-learn&#xff1a; pip install scikit-learn导入基本模块…

Tcon技术和Tconless技术介绍

文章目录 TCON技术&#xff08;传统时序控制器&#xff09;定义&#xff1a;主要功能&#xff1a;优点&#xff1a;缺点&#xff1a; TCONless技术&#xff08;无独立时序控制器&#xff09;定义&#xff1a;工作原理&#xff1a;优点&#xff1a;缺点&#xff1a; TCON与TCONl…

计算机基础(下)

内存管理 内存管理主要做了什么&#xff1f; 操作系统的内存管理非常重要&#xff0c;主要负责下面这些事情&#xff1a; 内存的分配与回收&#xff1a;对进程所需的内存进行分配和释放&#xff0c;malloc 函数&#xff1a;申请内存&#xff0c;free 函数&#xff1a;释放内存…

【青牛科技】TS223 单触摸键检测IC

概 述 &#xff1a; TS223是 触 摸 键 检 测 IC&#xff0c; 提 供 1个 触 摸 键 。 触 摸 检 测 IC是 为 了用 可 变 面 积 的 键 取 代 传 统 的 按 钮 键 而 设 计 的 。低 功 耗 和 宽 工 作 电压是 触 摸 键 的 DC和 AC特 点 。TS223采 用 SSOP16、 SOT23-6的 封 装 形 式…

CUDA补充笔记

文章目录 一、不同核函数前缀二、指定kernel要执行的线程数量三、线程需要两个内置坐标变量来唯一标识线程四、不是blocksize越大越好&#xff0c;上限一般是1024个blocksize 一、不同核函数前缀 二、指定kernel要执行的线程数量 总共需要线程数是&#xff1a; 1 * N N个线程…

“华为杯”研究生数学建模比赛历年赛题汇总(2004-2024)

文章目录 赛题链接历年赛题2004年赛题2005年赛题2006年赛题2007年赛题2008年赛题2009年赛题2010年赛题2011年赛题2012年赛题2013年赛题2014年赛题2015年赛题2016年赛题2017年赛题2018年赛题2019年赛题2020年赛题2020年赛题2021年赛题2022年赛题2023年赛题2024年赛题 赛题链接 部…

Python学习指南 + 谷歌浏览器如何安装插件

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 目录 前言 Python 官方文档的使用 谷歌浏览器中如何安装插件 前言 在学习Python时&#xff0c;我们可能会出现这样的困惑&#x…

java写一个石头剪刀布小游戏

石头剪刀布是一款经典的手势游戏,通常由两人参与,玩法简单且充满趣味。玩家通过出示手势代表“石头”、“剪刀”或“布”,并根据规则比较手势决定胜负。它广泛用于休闲娱乐、决策或解压活动。 一、功能简介 用户与计算机对战。 用户输入选择:石头、剪刀或布。 计算机随机生…

docker如何安装redis

第一步 如果未指定redis&#xff0c;则安装的是最新版的 docker pull redis 创建一个目录 mkdir /usr/local/docker/redis 然后直接可以下载redis&#xff0c;这是方式确实不怎么好&#xff0c;应该找在官网上找对应的redis配置文件 wget http://download.redis.io/redis-stab…

【作业九】RNN-SRN-Seq2Seq

点击查看作业内容 目录 1 实现SRN &#xff08;1&#xff09;使用numpy实现 &#xff08;2&#xff09;在&#xff08;1&#xff09;的基础上&#xff0c;增加激活函数tanh &#xff08;3&#xff09;使用nn.RNNCell实现 &#xff08;4&#xff09;使用nn.RNN实现 2 使用R…

利用Docker容器技术部署发布web应用程序

Docker是什么&#xff1f; docker 是一个开源的应用容器引擎&#xff0c;可以帮助开发者打包应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化&#xff0c;容器是完全使用沙箱机制&#xff0c;相互之间不会有任何…

【AI学习】Mamba学习(十八):S6的硬件感知设计

上一篇Mamba的文章提到&#xff0c;S6 models这个名称的由来是&#xff1a;S4 models with a selection mechanism and computed with a scan。 所以&#xff0c;S6模型首先是选择机制&#xff1a;先前模型的一个关键限制对选择性复制和归纳等重要合成任务不够适用&#xff0c…

Bug Fix 20241122:缺少lib文件错误

今天有朋友提醒才突然发现 gitee 上传的代码存在两个很严重&#xff0c;同时也很低级的错误。 因为gitee的默认设置不允许二进制文件的提交&#xff0c; 所以PH47框架下的库文件&#xff08;各逻辑层的库文件&#xff09;&#xff0c;以及Stm32Cube驱动的库文件都没上传到Gi…