美文网首页程序员
如何在Java 8中创建线程安全的ConcurrentHashS

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

作者: 勤奋的码农 | 来源:发表于2019-03-08 16:36 被阅读3次

在JDK 8之前,无法在Java中创建大型,线程安全的ConcurrentHashSet。该java.util.concurrent包没有一个叫做ConcurrentHashSet的类,但是从JDK 8开始,可以使用新添加的keySet(默认值)和newKeySet()方法在Java中创建一个由ConcurrentHashMap支持的ConcurrentHashSet。这比旧的解决方案更好。keySet(defaultValue)和newKeySet()返回的SetJDK 8的方法是一个合适的集合,还可以添加新元素以及执行其他集合操作,例如contains(),remove()等。

这些方法只能在ConcurrentHashMap类中使用而不能在ConcurrentMap接口中使用,所以需要使用ConcurrentHashMap 引用变量来保存引用,或者可以使用类型转换来转换ConcurrentHashMap对象存储在ConcurrentMap变量中。

  1. Java中的并发集合
    Java Concurrency API具有流行Collection类的并发版本,例如用于ArrayList的CopyOnArrayList,用于HashMap的ConcurrentHahsMap和用于HashSet的CopyOnWriteArraySet,但没有Java中的ConcurrentHashSet。 即使CopyOnWriteArraySet的线程安全,它也不适合大型线程安全集的应用程序。它仅用于设置大小保持较小且只读操作数量远远超过写入操作的应用程序。 所以,当你向Java程序员询问如何创建ConcurrentHashSet时,没有编写自己的类,很多人会说他们可以使用具有相同值的ConcurrentHashMap。事实上,这也是Java创建HashSet的方法。

但是,这种方法的问题是只有一个map而没有set,它不能使用虚拟值对ConcurrentHashMap执行set操作。当某些方法需要Set时,你不能传递它,因此它不是很有用。

另一个选项是,许多Java程序员会提到,可以通过调用keySet()方法从ConcurrentHashMap获得一个Set视图,而keySet()方法实际上返回一个Set,也可以在其中执行Set操作,并将其传递给一个需要Set的方法,但这种方法也有其局限性。也将反映在Set中。另一个限制是无法在此键集中添加新元素,这样做会抛出UnsupportedOperationException。

image.png

无论如何,这两个限制都已经成为了过去式,因为JDK 8添加了newKeySet()方法,该方法返回由给定类型的ConcurrentHashMap支持的Set,其中值为Boolean.TRUE。

与keySet()方法返回的Set视图不同,还可以将新对象添加到此Set中。该方法也被重载并接受初始容量以防止Set的大小调整。

1.1使用newKeySet()的ConcurrentHashSet

创建ConcurrentHashSet的代码示例:

Set<String> 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))。

1.2使用keySet的ConcurrentHashSet(默认值)

以下是使用keySet(映射值)方法获取ConcurrentHashSet的示例:

```ConcurrentHashMap&ltString, Integer> certificationCosts = new ConcurrentHashMap<>();

Set<String>concurrentHashSet = certificationCosts.keySet(246); 
concurrentSet.add("Spring enterprise"); // 值为246```
你也可以用这个Set 执行其他Set操作,例如addAll(),remove(),removeAll(),retainAll(),contains()。
![1d82fd35-7688-476c-b13d-7b512ed118ed.jpg](https://img.haomeiwen.com/i16358970/632581994517c92f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

从ConcurrentHashMap创建ConcurrentHashSet
这是我使用java.util.concurrent.ConcurrentHashMap类中添加的新方法创建的大型,线程安全的并发集的完整的程序。

```import java.util.Set; 
import java.util.concurrent.ConcurrentHashMap; 
/* 
* 从Map中删除键值对的程序
* 迭代 
*/ 
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");
 // 将抛出UnsupportedOperationExcetpion System.out.println("after adding element into concurrent set: " + concurrentSet); 
// 使用newKeySet()方法 Set 在Java 8中创建并发哈希集

concurrentHashSet = certificationCosts 。newKeySet();
concurrentHashSet.add("OCEJWCD");
concurrentHashSet.contains("OCEJWCD"); 
concurrentHashSet.remove("OCEJWCD"); 

System.out.println("after adding element into concurrent HashSet:" + concurrentSet); 

// 可以使用keySet(defaultValue)方法将元素添加到Set 
concurrentSet = certificationCosts.keySet(246); 
concurrentSet.add("Spring enterprise"); 
// 值是246
} 
}

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,如下所示: java.util.concurrent.ConcurrentHashMap $ 中线程“main”中的异常java.lang.UnsupportedOperationException Demo.main中的KeySetView.add(ConcurrentHashMap.java:4594) (Demo.java:23)

这就是我注释代码的原因,但是,由newKeySet()和keySet(mapping value)方法返回的Set允许向集合中添加新元素,这里没有错误。

顺便说一下,这不是在Java中创建线程安全集的唯一方法。

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

1。它最适合于很小的应用程序,只读操作数量远远超过可变操作,并且需要在遍历期间防止线程之间的干扰。

2.它的线程是安全的。

3. rators不支持可变删除操作。

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

5. rators在构建迭代器时能够保持数组的快照不变。

这就是如何在Java 8中创建ConcurrentHashSet。

相关文章

  • 如何在Java 8中创建线程安全的ConcurrentHashS

    在JDK 8之前,无法在Java中创建大型,线程安全的ConcurrentHashSet。该java.util.c...

  • Java基础20-初识synchronized

    概述 如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题? 基本上所有的并发模式...

  • Java多线程干货系列—(二)synchronized

    前言 本篇主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非...

  • java多线程基础(二)

    简介 本次主要介绍java多线程中的同步,也就是如何在java语言中写出线程安全的程序。如何在java语言中解决非...

  • java_多线程

    java_多线程 线程创建方式;join用法; sleep和wait区别; 线程安全和不安全的java集合; St...

  • Java多线程

    目录 什么是多线程?引入多线程的意义何在? 并行和并发 线程安全 线程状态 如何保证线程安全? 创建线程的三种方法...

  • 多线程开发艺术之thread的使用

    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来、以及如何在Java中怎么创建线程...

  • 二:多线程之守护线程

    在Java中线程分为两种: 用户线程:即正常创建的线程,如负责下载、上传等耗时任务的线程 守护线程:在正常创建的线...

  • 设计模式系列之一单例模式

    Java实现 不考虑线程安全的写法 这种写法的问题在于非线程安全,当两个线程同时进入if判断,且新对象还未创建时,...

  • JAVA开发-常见面试题

    一、java多线程 线程池的原理,为什么要创建线程池? 线程的生命周期,什么时候会出现僵死进程? 什么是线程安全,...

网友评论

    本文标题:如何在Java 8中创建线程安全的ConcurrentHashS

    本文链接:https://www.haomeiwen.com/subject/zparpqtx.html