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;是您想学习容器技术不得不掌握的。本文将带您一步一…

排序出错Java_使用picard排序去重出错

命令&#xff1a;java -jar/public/home/nieyg/biosoft/package/picard-tools-1.124/picard.jar SortSam \I/public/home/nieyg/atacseq/data/Rawdata/align/LDN-D2-1.raw.bam\OLDN-D2-1.sort.bam \SORT_ORDERcoordinate错误信息&#xff1a;Exception in thread "main&qu…

移动端设备标识码/设备唯一标识码/设备唯一性

文章目录名词释义Android 设备标识码iOS设备标识码总结名词释义 Device ID&#xff1a;设备ID。 IMEI&#xff1a;International Mobile Equipment Identity&#xff0c;国际移动设备身份码的缩写。是由15位数字组成的“电子串号”&#xff0c;它与每台手机一一对应&#xff0…

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…

aws实例启动失败_AWS:启动安装了APOC的Neo4j实例

aws实例启动失败安装Neo4j之后&#xff0c;我要做的第一件事就是安装APOC库 &#xff0c;但是我发现在AWS上旋转服务器时这是一个手动过程&#xff0c;所以我想简化一下。 已经有一个Neo4j AMI可以安装Neo4j 3.2.0 &#xff0c;我的同事Michael指出&#xff0c;我们可以通过编…

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

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

QPW 点评表(tf_appraise)

点评表 CREATE TABLE tf_appraise (appraise_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 点评ID,company_id bigint(20) DEFAULT NULL COMMENT 企业ID,user_id bigint(20) DEFAULT NULL COMMENT 用户ID,avg_score decimal(4,2) DEFAULT 0.00 COMMENT 综合评分,contributi…

python多次输入数据_如何用python3输出重复的数据?

面对很多重复的数据&#xff0c;如果人工一个个处理起来会很麻烦&#xff0c;而且要浪费大量的时间和精力。之前就python处理数据是简单便捷的&#xff0c;有没有一种方法能把重复的数据输出出来&#xff0c;这样就一目了然了。相信有一些小伙伴也跟小编有同样的困扰&#xff0…

java magic number_避免JDBC查询中的CheckStyle magic number错误

我正在上课一个小组项目,我们正在尝试CheckStyle.我对Java非常满意,但从未触及到JDBC或在此之前完成任何数据库工作.我想知道如果有一个优雅的方式来避免在准备语句电话中出现错误的数字错误,请考虑&#xff1a;preparedStatement connect.prepareStatement("INSERT INTO…

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

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

MySQL命令之show用法详解

文章目录参考示例&#xff08;一&#xff09;查看表字段详情&#xff08;二&#xff09;显示某个表的创建语句&#xff08;三&#xff09;显示所有数据库的名称&#xff08;四&#xff09;查看已选数据库中的所有表&#xff08;五&#xff09;查看某个数据库的创建语句&#xf…

java关闭websocket_关闭代码1006关闭websocket的原因

关闭代码1006是一种特殊的代码&#xff0c;它表示浏览器实现异常(本地)关闭了连接。在websocket.onerror(evt)事件中查看详细信息。但是&#xff0c;Chrome很少会向JavaScript端报告任何接近代码1006的原因。这可能是由于WebSocket规范中的客户端安全规则所致&#xff0c;以防止…

python生成c语言代码_Python爬取C语言中文网教程生成PDF

[Python] 纯文本查看 复制代码import requests from lxml import etree import re import os import pdfkit def gethtml(url,encode): r requests.get(url) r.encoding encode return r.text def writehtml(path,str): f open(path,w,encodingutf-8) f.write(str) f.close …

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

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

QPW 提现申请单表(暂时不做)(tf_cash_apply)

提现申请单表 这是用户提现申请单表&#xff0c;这是一种申请单据。 CREATE TABLE tf_cash_apply (cash_apply_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 申请单ID,cash_order_no bigint(20) NOT NULL UNIQUE COMMENT 提现申请单编号, # 补cash_order varchar(100) NOT…

服务器一键建php网站,搭建服务器 - 我的lnmp一键安装报错 - php中文网博客

https://blog.csdn.net/weixin_34187862/article/details/87668648 链接/usr/local/nginx/conf/nginx.confuser www www;worker_processes auto;error_log /home/wwwlogs/nginx_error.log crit;pid /usr/local/nginx/logs/nginx.pid;#Specifies the value for maximum file …

python控制其它软件_从另一个脚本控制python脚本

我正在尝试学习如何编写一个脚本control.py,它在循环中运行另一个脚本test.py一定次数,在每次运行中,读取其输出并在打印某些预定义输出时暂停它(例如文本’现在停止’),并且循环继续其迭代(一旦test.py完成,无论是单独还是强制).所以有一些事情&#xff1a; for i in range(n)…

QPW 用户签署协议日志表(tf_user_agreement_log)

用户签署协议日志表 CREATE TABLE tf_user_agreement_log (log_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 日志ID,user_id bigint(20) DEFAULT NULL COMMENT 用户ID,agree_id int(11) DEFAULT NULL COMMENT 协议ID,agree_code varchar(32) DEFAULT NULL COMMENT 协议编号…

std::tostring_枚举:如何正确使用name()和toString()方法

std::tostring两种方法之间的区别&#xff1f; Java枚举有两种方法来检索枚举常量的值&#xff1a; name&#xff08;&#xff09;和.toString&#xff08;&#xff09; 。 toString&#xff08;&#xff09;方法调用name&#xff08;&#xff09;方法&#xff0c;该方法返回枚…

php数组按时间排序,按日期时间在PHP中对数组中的数组进行排序

我目前在PHP中有一个问题,我想按照创建日期对这些帖子进行排序,以便它们可以按降序显示.我一直在寻找一个PHP函数来做到这一点,但没有运气.有一个简单的解决方案吗&#xff1f;任何想法将不胜感激:)array0 >arraypost_id > string 1 (length1)user_id > string 3 (len…