如何在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,一经查实,立即删除!

相关文章

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

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

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

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

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

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

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;设置…

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

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

Java命令行界面(第15部分):Jargo

Jargo在其GitHub主页上定义为“一种减轻程序参数/选项处理的工具”。 当已经存在许多其他命令行处理库时&#xff0c;该页面为另一个命令行处理库提供了基本原理 &#xff0c;该列表的顶部是“因为类型安全性&#xff0c;不变性和可读性很重要”。 Jargo的选项“定义”阶段使用…

java中序列化与反序列化_Java中的序列化

java中序列化与反序列化Java提供了一种称为序列化的机制&#xff0c;以按字节的有序或字节序列的形式持久化Java对象&#xff0c;其中包括对象的数据以及有关对象的类型和存储在对象中的数据类型的信息。 因此&#xff0c;如果我们已序列化了任何对象&#xff0c;则可以使用对象…

Java命令行界面(第3部分):jbock

在本系列中有关使用Java进行命令行分析的前两篇文章中&#xff0c;我介绍了Apache Commons CLI和args4j库。 在本系列的第三篇文章中&#xff0c;我将介绍jbock &#xff0c;它是自我描述的“非常简单的CLI解析器”。 我在Java中进行命令行解析的文章使用了一些示例&#xff0…

java collection详解_java 7 collection 详解(一)

一、综述java集合框架定义了几个接口&#xff0c;这些接口决定了collection类的基本特性。不同的是&#xff0c;具体类仅仅是提供了标准接口的不同实现&#xff0c;如图&#xff0c;java集合框架接口图从图可知&#xff0c;java集合类的主要是由两个接口派生而出——Collection…

jsf tree组件_JSF:在传统组件和时尚性能杀手之间进行选择

jsf tree组件这篇博客文章起源于一个大型Web应用程序中的性能问题。 每个人都优化Java代码&#xff0c;但似乎没有人尝试优化JavaScript代码。 奇怪&#xff0c;因为在客户端有很多改进的空间。 我会说&#xff0c;甚至比服务器端还要多。 我们将分析可编辑的JSF标准组件&#…

如何在Java中转义JSON字符串-Eclipse IDE技巧

在Java应用程序中工作或进行JSON解析时&#xff0c;通常很常见的做法是从某些资源&#xff08;例如RESTful Web服务&#xff09;中复制粘贴JSON字符串&#xff0c;然后使用Jackson库解析JSON。 这是测试和学习Java中解析JSON字符串的最快方法&#xff0c;但是这种方法的主要问题…

spring javafx_带有Spring的JavaFX 2

spring javafx我将从一个大胆的声明开始&#xff1a;我一直很喜欢Java Swing或applet。 在那里&#xff0c;我说了。 如果我进行一些自我分析&#xff0c;那么这种钦佩可能是在我接触Java时开始的。 Swing&#xff08;实际上&#xff09;是我使用Java所做的第一件事&#xff0c…

jframe和mysql登陆_刚写的一个从数据库读取账户和密码进行登陆的小程序~高手请无~...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.sql.Connection;import java.sql.DriverManager;import java.sql.*; import javax.swing.*;public class LoginSystem extends JFrame{publi…

mycat mysql 物理部署_一、MyCat的搭建

一、什么是mycat简单直接点就是&#xff0c;MyCat其实就是一个数据库的中间件&#xff01;一般我们都是app直接到数据库&#xff01;有了MyCat以后&#xff0c;就是app到MyCat然后再访问数据库。mycat是个中间件&#xff0c;它负责连接管理mysql,应用程序连接mycat,把mycat当作…

Apache Camel中的短重试与长重试

《骆驼设计模式》一书介绍了20种模式以及用于设计基于Apache Camel的集成解决方案的众多技巧和最佳实践。 每个模式都基于真实的用例&#xff0c;并提供了Camel特定的实现细节和最佳实践。 为了让您有这本书的感觉&#xff0c;以下是该书的重试模式摘录&#xff0c;其中介绍了如…

java实现驾校考试系统_jsp驾校考试系统

本驾校考试系统采用了Browser/Server体系结构&#xff0c;JSP(Java Server Page)作为前台开发工具&#xff0c;MySQL作为后台数据库进行开发。最终系统实现的系统将分为管理员和学员两个角色&#xff0c;其中系统管理员部分的主要功能包括修改登录密码、学员信息管理、科目1题目…

java qlv转mp4 代码_怎么将qlv格式转换成mp4?教你快速转换视频格式的技巧

如何将qlv格式转换成mp4?众所周知qlv格式是腾讯视频的下载格式&#xff0c;而qlv格式的特点在于不能用别的播放器打开。如果用腾讯视频以外的播放器打开则需要将qlv格式转换成mp4&#xff0c;那你知道将qlv格式转换成mp4的技巧吗&#xff1f;下面小编教你一种转换qlv格式的技巧…