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

java 线程中创建线程

在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。 此方法返回ConcurrentHashMap中的键的Set视图,并使用给定的所有添加默认默认值(即Collection.add和Collection.addAll(Collection))。

当然,这只能用于您可以对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

java 线程中创建线程

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

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

相关文章

docker 删除所有镜像_关于 Docker 镜像的操作,看完这篇就够啦 !(下)| 文末福利...

紧接着上篇《关于 Docker 镜像的操作&#xff0c;看完这篇就够啦 !(上)》&#xff0c;奉上下篇 &#xff01;&#xff01;&#xff01;镜像作为 Docker 三大核心概念中最重要的一个关键词&#xff0c;它有很多操作&#xff0c;是您想学习容器技术不得不掌握的。本文将带您一步一…

python与access选哪个_从Python连接到Access

I want to be connected to a database Boreas (Access) from Python. How to be connected from Python to Access database Northwind? 解决方案 Here are 2 ways, with COM dispatch and with odbc. You will need the pywin32 extensions and/or pyodbc to use these meth…

设备唯一标识/设备码/设备标识码

文章目录一、MAC地址二、IMEI三、MEIDMEID 和 IMEI 用途的区别四、序列号&#xff08;一&#xff09;苹果手机序列号&#xff08;二&#xff09;华为手机序列号一、MAC地址 MAC地址&#xff08;英语&#xff1a;Media Access Control Address&#xff09;&#xff0c;直译为媒…

java登录界面命令_Java命令行界面(第18部分):JCLAP

java登录界面命令Giles Winstanley的JCLAP &#xff08; Java命令行参数解析器 &#xff09;是基于Java的命令行处理库的系列文章中介绍的第18个库。 这篇文章的示例基于JCLAP 1.4 &#xff0c;它需要Java 8 。 JCLAP主页上指出&#xff1a;“ JCLAP帮助Java开发人员为其应用程…

java登录界面命令_Java命令行界面(第15部分):Jargo

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

没学过编程能学python吗_我没学过编程,能否学会Python?

学习Python编程语言&#xff0c;是大家走入编程世界的最理想选择。那么我没学过编程&#xff0c;能否学会Python?上海Python培训肯定的回答您&#xff1a;of course!完全能学会!设计大师说过&#xff0c;留白是很好的风景&#xff0c;适当的留白是设计的至高境界;对于没有编程…

java登录界面命令_Java命令行界面(第13部分):JArgs

java登录界面命令JArgs 1.0的区别在于&#xff0c;这是我的第13篇文章的主题&#xff0c;该文章是关于Java命令行参数解析的。 JArgs是一个开放源代码&#xff08; BSD许可 &#xff09;库&#xff0c;主要由Steve Purcell和Ewan Mellor等 不同贡献者支持。 事实证明&#xff0…

java登录界面命令_Java命令行界面(第11部分):CmdLn

java登录界面命令这篇文章介绍了如何使用Ostermiller Java Utilities 1.08.02的CmdLn&#xff08;Java命令行解析器&#xff09;来处理基于Java的应用程序中的命令行参数。 Ostermiller Java实用程序包括几种不同类型的实用程序 &#xff0c;但本文的重点是组件页面上描述的“命…

socket模拟http的登陆_Python网络爬虫之模拟登陆 !

为什么要模拟登陆&#xff1f;Python网络爬虫应用十分广泛&#xff0c;但是有些网页需要用户登陆后才能获取到信息&#xff0c;所以我们的爬虫需要模拟用户的登陆行为&#xff0c;在登陆以后保存登陆信息&#xff0c;以便浏览该页面下的其他页面。保存用户信息模拟登陆后有两种…

java登录界面命令_Java命令行界面(第12部分):CLAJR

java登录界面命令第十二篇有关在Java中处理命令行参数的文章的特色库是带有Java Reflection的命令行参数 &#xff08;CLAJR&#xff09;。 该“库”是单个Java源文件&#xff08; CLAJR-0.9.java &#xff09;&#xff0c; 可从SourceForge下载 。 CLAJR的主页当前显示2006年版…

openssh rpm包_100台CentOS7要升级OpenSSH怎么办?

背景现在有 100 台 Centos7 需要升级 OpenSSH 到 8.3&#xff0c;怎么办呢&#xff1f;一台台的操作显然不符合我摸鱼的风格&#xff0c;既然每台操作都一样&#xff0c;Ansible Roles 就有用武之地了。正常升级流程首先 rpmbuild 打出 OpenSSH 8.3 的 RPM 包&#xff0c;rpm -…

java 从一个容器获取对象,如何从 Spring IoC 容器中获取对象?

前面几篇文章主要分析了 Spring IoC 容器如何初始化&#xff0c;以及解析和注册我们定义的 bean 信息。其中&#xff0c;「Spring 中的 IoC 容器」对 Spring 中的容器做了一个概述&#xff0c;「Spring IoC 容器初始化」和「Spring IoC 容器初始化(2)」分析了 Spring 如何初始化…

thymeleaf与jsp_PagingAndSortingRepository –如何与Thymeleaf一起使用

thymeleaf与jsp在本教程中&#xff0c;我将演示如何通过分页显示Thymeleaf中的企业客户列表。 1 –项目结构 我们有一个正常的Maven项目结构。 2 –项目依赖性 除了正常的Spring依赖关系之外&#xff0c;我们还添加Thymeleaf和hsqldb&#xff0c;因为我们使用的是嵌入式数据…

MySQL 批量生成 SQL 脚本语句解决实际的业务需求/如何拼接字符串/拼接字符串的 SQL 语句

文章目录实际需求分析思路写拼接 SQL 脚本的脚本语句执行得到脚本语句保存成 SQL 脚本文件实际需求 有些行政区域的字段 area_fullname 是空的&#xff0c;如何补全呢&#xff1f;如下所示&#xff1a; 分析思路 &#xff08;一&#xff09;如何取到每个区域的上级名称和上…

php的变量都放在哪里,php变量一般放在哪个位置

php变量一般放在哪个位置php定义变量的要求格式&#xff0c;是非常宽松的&#xff0c;至于在哪里定义变量就需要看你的需求&#xff0c;可以在构造函数&#xff0c;也可以在你定义的方法中定义局部变量&#xff0c;也可以在构造函数外面定义全局变量。// 局部变量 函数内部func…

oauth2令牌刷新_了解OAuth2令牌认证

oauth2令牌刷新1.简介 在本教程中&#xff0c;我们将了解OAuth2令牌身份验证 &#xff0c;以便只有经过身份验证的用户和应用程序才能获得有效的访问令牌&#xff0c;该令牌随后可用于访问服务器上的授权API&#xff08;在OAuth术语中仅是受保护的资源&#xff09;。 使用基于…

jsap支付_Java命令行界面(第20部分):JSAP

jsap支付JSAP &#xff08; Java Simple Argument Parser &#xff09;2.1是本系列文章的第二十篇&#xff0c;重点是处理Java的命令行参数。 JSAP页面描述了该库存在的原因&#xff1a;“我在Internet上找到了多个解析器&#xff0c;所有解析器都处理了开关&#xff0c;但是没…

python语句大全input_input提示文字 Python基础输入函数,if-else语句,if-elif

input&#xff08;&#xff09;函数 此功能用于获取用户输入。 &#xff08;调用1&#xff09;input后&#xff0c;程序将立即暂停并等待用户输入。在用户完成内容输入后&#xff0c;单击Enter&#xff0c;程序将继续向下执行。 例如&#xff1a; input() &#xff08;2&#x…

ftp限流java,FTP流量限制的方法

一般来说&#xff0c;下载都是通过FTP来实现的&#xff0c;这样简单的采用ACLs就可以实现的。不过这样存在一个问题&#xff0c;就是原来正常的网络访问也给禁止了&#xff0c;无法继续工作&#xff0c;另外&#xff0c;还有大量的DOWNLOAD不通过FTP&#xff0c;而是借助HTTP协…

argparser_Java命令行界面(第22部分):argparser

argparserJohn Lloyd的argparser是本系列的第二十二篇有关基于Java的命令行参数解析的文章中介绍的库。 该库的主页除了提供单个源代码示例外&#xff0c;还提供了指向基于Javadoc的API文档 &#xff0c;JAR文件&#xff0c;ZIP文件和TAR文件的链接。 本帖子中使用的示例与本系…