如何在Java 8中创建线程安全的ConcurrentHashSet?

在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet。 java.util.concurrent包甚至没有一个名为ConcurrentHashSet的类,但是从JDK 8开始,您可以使用新添加的keySet(默认值)和newKeySet()方法来创建由ConcurrentHashMap支持的ConcurrentHashSet。 与战术解决方案不同,例如将并发哈希映射与伪值一起使用或使用映射的设置视图,您无法在其中添加新元素。 JDK 8的keySet(defaultValue)和newKeySet()方法返回的Set是一个合适的集合,您还可以在其中添加新元素以及执行其他set操作,例如contains(),remove()等。这些方法仅在ConcurrentHashMap类中可用,而在ConcurrentMap接口中不可用,因此您需要使用ConcurrentHashMap变量来保存引用,或者需要使用类型转换来强制转换存储在ConcurrentMAp变量中的ConcurrentHashMap对象。

Java并发API具有流行的Collection类的并发版本,例如ArrayList的CopyOnArrayList,HashMap的ConcurrentHahsMap和HashSet的CopyOnWriteArraySet,但是Java中没有类似ConcurrentHashSet的东西。 即使CopyOnWriteArraySet是线程安全的,也不适合需要大型线程安全集的应用程序。 它仅用于集大小较小且只读操作远远超过写入操作的应用程序。

因此,当您向Java程序员询问如何在不编写自己的类的情况下创建ConcurrentHashSet时,许多人会说他们可以将ConcurrentHashMap与虚假值一起使用。 实际上,这也是Java所做的,因为如果您知道HashSet在内部使用具有相同值的HashMap。

但是,这种方法的问题是您有一个地图并且没有设置。 您不能使用虚拟值在ConcurrentHashMap上执行设置操作。 当某些方法需要一个集合时,您不能将其传递出去,因此它不是很有用。

另一个选择是,许多Java程序员都会提到您可以通过调用keySet()方法从ConcurrentHashMap中获取Set视图,该方法实际上返回一个Set,您可以在其中执行Set操作并将其传递给需要Set的方法。但是这种方法也有其局限性,例如Set由ConcurrentHashMAp支持,并且Map中的任何更改也将反映在Set中。 另一个限制是您不能在此键集中添加新元素,否则将引发UnsupportedOperationException。 看到
Java 8 in Action了解更多信息。

这两个限制现在已成为过去,因为JDK 8添加了newKeySet()方法,该方法从给定类型(其中值为Boolean.TRUE)返回由ConcurrentHashMap支持的Set。 与从keySet()方法返回的Set视图不同,您还可以将新对象添加到此Set中。 该方法也很重载,并且接受初始容量以防止Set的大小调整。

以下是在Java 8中创建ConcurrentHashSet的代码示例:

ConcurrentHashMap certificationCosts = new ConcurrentHashMap<>();
Set concurrentHashSet = certificationCosts.newKeySet();
concurrentHashSet.add("OCEJWCD"); //OK
concurrentHashSet.contains("OCEJWCD"); //OK
concurrentHashSet.remove("OCEJWCD"); //OK

顺便说一句,这并不是用Java创建并发的,大的,线程安全的Set的唯一方法。 您还可以使用新添加的,重载的keySet(默认值)方法来创建ConcurrentHashSet。 此方法使用给定的任何默认添加默认值(即Collection.add和Collection.addAll(Collection))返回ConcurrentHashMap中键的Set视图。

当然,这只能用于您可以对Set中的所有元素使用相同的值,这在大多数情况下是可以的,因为您实际上并不关心Set中的值。 请记住,HashSet还是一个对所有元素都具有相同值的HashMap,有关更多详细信息,请参见HashSet在Java内部的工作方式 。

这是在Java 8中使用keySet(mapped value)方法获取ConcurrentHashSet的示例:

ConcurrentHashMap certificationCosts = new ConcurrentHashMap<>();
Set concurrentHashSet = certificationCosts.keySet(246); 
concurrentSet.add("Spring enterprise"); // value will be 246 but no error

您还可以与此Set一起执行其他Set操作,例如addAll(),remove(),removeAll(),retainAll(),contains()。 它也是线程安全的,因此可以在多线程Java应用程序中使用。 您可以了解有关真正不耐烦的Java SE 8上基于集合的操作的更多信息。

Java程序,用于从ConcurrentHashMAp创建ConcurrentHashSet。

这是我们完整的Java程序,它使用在java.util.concurrent.ConcurrentHashMap类上添加的新方法在Java 8中创建大型的线程安全的并发哈希集。

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;/*
* Java Program to remove key value pair from Map while 
* iteration. 
*/
public class Demo {public static void main(String[] args) throws Exception {ConcurrentHashMap certificationCosts = new ConcurrentHashMap<>();
certificationCosts.put("OCAJP", 246);
certificationCosts.put("OCPJP", 246);
certificationCosts.put("Spring Core", 200);
certificationCosts.put("Spring Web", 200);
certificationCosts.put("OCMJEA", 300);Set concurrentSet = certificationCosts.keySet();System.out.println("before adding element into concurrent set: " + concurrentSet);
// concurrentSet.add("OCEJWCD"); // will throw UnsupportedOperationExcetpion
System.out.println("after adding element into concurrent set: " + concurrentSet);// creating concurrent hash set in Java 8 using newKeySet() method
Set concurrentHashSet = certificationCosts.newKeySet();concurrentHashSet.add("OCEJWCD");
concurrentHashSet.contains("OCEJWCD");
concurrentHashSet.remove("OCEJWCD");
System.out.println("after adding element into concurrent HashSet: " + concurrentSet);// you can also use keySet(defaultValue) method to add element into Set
concurrentSet = certificationCosts.keySet(246); 
concurrentSet.add("Spring enterprise"); // value will be 246 but no error}}Output
before adding an element into the concurrent set: 
[Spring Web, OCPJP, OCAJP, Spring Core, OCMJEA]
after adding an element into the concurrent set: 
[Spring Web, OCPJP, OCAJP, Spring Core, OCMJEA]
after adding an element into concurrent HashSet: 
[Spring Web, OCPJP, OCAJP, Spring Core, OCMJEA]

您可以看到,如果尝试将新对象添加到由ConcurrentHashMAp的keySet()方法返回的Set中,则会抛出UnsupportedOperationExcepiton,如下所示:

线程“ main”中的异常java.lang.UnsupportedOperationException

在java.util.concurrent.ConcurrentHashMap $ KeySetView.add(ConcurrentHashMap.java:4594)在Demo.main(Demo.java:23)

这就是为什么我注释了该代码,但是,newKeySet()和keySet(mapped value)方法返回的Set允许您将新元素添加到Set中,那里没有错误。

顺便说一下,这不是用Java创建线程安全Set的唯一方法。 甚至在Java 8之前,都有一个名为CopyOnWriteArraySet的类,该类允许您在Java中创建线程安全集。 它类似于CopyOnWriteArrayList,并且仅适用于集合大小小的应用程序,并且您只读取唯一的操作,因为它每次写入时都会将Set中的所有元素复制到新的Set中。 有关真正不耐烦的信息 ,请参阅Java SE 8,以了解有关Java 8中并发集合的更多信息。

以下是CopyOnWriteArraySet的一些重要属性:

1.它最适合于集大小通常较小的应用,只读操作远远多于可变操作,并且您需要防止遍历期间线程之间的干扰。

2.这是线程安全的。

3.可变操作(添加,设置,删除等)非常昂贵,因为它们通常需要复制整个基础数组。

4.迭代器不支持可变删除操作。

5.通过迭代器的遍历速度很快,不会遇到其他线程的干扰。

6.迭代器在构造迭代器时依赖于数组的不变快照。

这就是如何在Java 8中创建ConcurrentHashSet的全部内容。 JDK 8 API不仅具有lambda表达式和流之类的主要功能,而且还具有这些小的更改,这些使您的日常编码更加容易。 使用newKeySet()方法在Java中创建ConcurrentHashSet并非易事。 您不需要使用带有伪造值的集合之类的地图,也不必使用keySet()返回的集合视图的局限性,后者不允许您向集合中添加新元素。

进一步阅读

  • 使用Lambda表达式从Java 8中的集合到流
  • Java 8中用于数据处理的流,收集器和可选项
  • Java 8实战

相关文章:

如何用Java 8编写Comparator?
如何在Java 8中读取文件?
如何在Java 8中加入String? 如何在Java 8中比较日期? 如何在Java 8中格式化日期? 如何在Java 8中对列表排序?

非常感谢您阅读本文。 如果您喜欢本教程,请与您的朋友和同事分享。

翻译自: https://www.javacodegeeks.com/2017/08/create-thread-safe-concurrenthashset-java-8.html

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

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

相关文章

rust如何在木板上上传图片_通过编写一个简单的游戏来学习 Rust | Linux 中国

导读&#xff1a;你可以尝试以多种语言编程一个简单的游戏来开始编程之路。本文字数&#xff1a;4068&#xff0c;阅读时长大约&#xff1a; 5分钟https://linux.cn/article-12979-1.html作者&#xff1a;Moshe Zadka译者&#xff1a;Xingyu.Wang当你想学习一门新的编程语言时&…

python神经网络教程16_Python深度学习之神经网络视频

Python深度学习之神经网络视频课程简介该阶段是深度学习的入门课程&#xff0c;主要介绍经典的深度学习框架TensorFlow的使用&#xff0c;IO操作&#xff0c;以及神经网络基础、卷积神经网络的相关知识&#xff0c;并用卷积神经网络原理搭建、设计自己的网络&#xff0c;实现对…

apache camel_REST与Apache Camel

apache camel有许多方法可以在Camel中公开HTTP终结点&#xff1a;jetty&#xff0c;tomcat&#xff0c;servlet&#xff0c;cxfrs和restlet。 其中的两个组件– cxfrs和restlet也仅需几行代码即可支持REST语义。 这个简单的示例演示了如何使用camel-restlet和camel-jdbc进行CRU…

删除 多个表_合并汇总多个工作簿多个工作表,删除修改新增更新内容只需刷新...

要求&#xff1a;1、把多个工作簿的多个工作表内容合并汇总2、后续在任一工作表内删除修改新增内容&#xff0c;无需再重新做表3、后续在任一工作簿中新增一个或多个工作表&#xff0c;无需再重新做表4、后续在文件夹中添加一个或多个Excel工作簿文件&#xff0c;无需再重新做表…

OAuth2,JWT,Open-ID Connect和其他令人困惑的事物

免责声明 如果觉得我必须从一个重要的免责声明开始这篇文章&#xff1a; 不要太相信我要说的话。 我之所以这样说&#xff0c;是因为我们正在讨论安全性。 而且&#xff0c; 当您谈论安全性时&#xff0c;除了100&#xff05;正确的陈述外&#xff0c;还有冒任何其他风险的风险…

go语言查询某个值是否在数组中_go语言中的数组

package main;import ("fmt")func main() {//声明一个数组var a [3]int;a [3]int{1, 2, 3};//声明并赋值var b [3]int [3]int{1, 2, 3};//声明并赋值(省略类型)var c [3]int{1, 2, 3};//声明并赋值简写d : [3]int{1, 2, 3};//GO中将数组长度作为数组类型的一部分/…

ssm集成笔记_SSM整合笔记

SSM一般是分开学的&#xff0c;Spring&#xff0c;SpringMVC&#xff0c;Mybatis。学完之后整合也是需要学习一段时间。下面是一次整合的实践...SSM的整合顺序一般先整合Spring和Mybatis。再整合SpringMVC。Spring整合Mybatis首先把文件放到lib的文件夹下。然后在src目录下新建…

人工智能在建筑运营_打造智能建筑商

人工智能在建筑运营构建API时&#xff0c;您应始终考虑谁将使用它。 当API简单易用时&#xff0c;用户就会感到满意。 当用户满意时&#xff0c;每个人也都会满意。 但是出色的可用性并非总是容易实现的。 有一些模式对此有所帮助&#xff0c;在这篇文章中&#xff0c;我将重点…

mysql删除用户账号和密码_mysql添加、删除用户和授权用户

MySql中添加用户,新建数据库,用户授权,删除用户,修改密码(注意每行后边都跟个;表示一个命令语句结束):1.新建用户1.1 登录MYSQL&#xff1a;>mysql -u root -p>密码1.2 创建用户&#xff1a;mysql> insert into mysql.user(Host,User,Password) values("localhos…

从GWT开发人员的角度概述Scala.js

该博客严重偏向于GWT&#xff08;和基于GWT的框架&#xff09;&#xff0c;但是我们牢记未来GWT可能会被其他技术所取代&#xff0c;因此我们始终愿意探索其他平台/框架。 正如他们所说&#xff0c;多元化可以降低风险。 每种编程语言&#xff0c;甚至最奇怪的编程语言&#xf…

alinq mysql_ALinq让Mysql变得如此简单_MySQL

当大家已经习惯了使用.net 去操作SQL Server&#xff0c;有多少人曾经尝试过使用.net 去操作Mysql数据库&#xff01;在.net 的光环下&#xff0c;Mysql是显得如此微不足道&#xff01;但是Mysql的开源又是如此具有诱惑。1. ADO.NET 方式连接Mysql数据库经过在网上查找资料&…

debian php mysql 安装_在 Debian 下安装 Apache,MySQL,PHP

我是转载过来的&#xff0c;原地址 http://blog.csdn.net/youngdze/article/details/20455557 ,我安装成功!首先&#xff0c;对你的源进行更新&#xff1a;$ sudo apt-get update第一步--安装 ApacheApache 是一个开源软件&#xff0c;它目前运行在全球超过 50% 的服务器上&…

java ee cdi_Java EE CDI bean范围

java ee cdiJava EE平台的上下文和依赖注入&#xff08;CDI&#xff09;是一项功能&#xff0c;有助于将Java EE平台的Web层和事务层绑定在一起。 CDI是一组服务&#xff0c;可以一起使用&#xff0c;使开发人员可以轻松地在Web应用程序中使用企业bean和JavaServer Faces技术。…

airflow mysql_Airflow 使用及原理分析

Airflow 入门及使用什么是 Airflow&#xff1f;Airflow 是一个使用 Python 语言编写的 Data Pipeline 调度和监控工作流的平台。Airflow 是通过 DAG(Directed acyclic graph 有向无环图)来管理任务流程的任务调度工具&#xff0c;不需要知道业务数据的具体内容&#xff0c;设置…

mysql关于死锁的优化_mysql死锁探究及优化

什么是锁&#xff1f;锁是计算机为了平衡协调多个进程或线程并发访问资源的机制。计算机除了cpu&#xff0c;ram&#xff0c;I/O&#xff0c;数据也是一种共享资源。锁冲突是影响数据库并发性能的一个重要因素。例如行锁&#xff0c;表锁等&#xff0c;读锁&#xff0c;写锁等&…

jdk8 calendar_JDK 8的Calendar.Builder

jdk8 calendar勇敢的Java新世界的定义特征之一是Java空间中构建器模式的日益普及。 Groovy是JVM上最流行的替代语言&#xff08;对于Java&#xff09;&#xff0c;以在核心库以及Groovy支持的库和框架中大量使用Builder而闻名。 Josh Bloch将该模式带到了Java开发人员社区的最前…

mt5 mysql数据库_Django -- 使用MySql数据库

Django默认使用的sqlite3&#xff0c;这在实际的生产环境中是不推荐的&#xff1b;1. 创建数据库Linux VM_0_15_centos 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux1.1. 使用utf8mb4编码mysql的utf-8编码最多只支持3个字节&…

gradle 安装_如何安装Gradle

gradle 安装Gradle是一个依赖管理/构建工具&#xff0c;结合了Maven和Ant的优点&#xff0c;使其成为功能强大且可自定义的工具。 它还使用了光滑的Groovy DSL而不是Maven和Ant的XML方法&#xff0c;并且当我开始一个新项目时&#xff0c;它是我个人的选择工具。 安装方法如下。…

wps怎么旋转页面_用WPS文字编辑一份试卷,详细教程来了,老师们赶快收藏吧

​ 试卷是每一个教师接触最多的资料了&#xff0c;很多教师在检测前找一些现成的试卷复印给学生练习&#xff0c;但是&#xff0c;有很多题不适合学生&#xff0c;因此&#xff0c;我们需要自己编辑一份试卷了&#xff0c;编辑试卷也并不是很难的&#xff0c;今天&#xff0c;就…

maven 部署nexus_Maven部署到Nexus

maven 部署nexus1.概述 在上一篇文章中 &#xff0c;我讨论了Maven项目如何在本地安装尚未部署在Maven Central&#xff08;或任何其他大型且公共托管的存储库&#xff09;上的第三方jar。 该解决方案仅适用于小型项目&#xff0c;在这些项目中安装&#xff0c;运行和维护完整的…