1. 程式人生 > >如何在Java 8中創建線程安全的ConcurrentHashSet

如何在Java 8中創建線程安全的ConcurrentHashSet

com stat 只讀 pri imp 大小 只有一個 保持 arrays

在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。

技術分享圖片

無論如何,這兩個限制都已經成為了過去式,因為JDK 8添加了newKeySet()方法,該方法返回由給定類型的ConcurrentHashMap支持的Set,其中值為Boolean.TRUE。

與keySet()方法返回的Set視圖不同,還可以將新對象添加到此Set中。該方法也被重載並接受初始容量以防止Set的大小調整。

1.1使用newKeySet()的ConcurrentHashSet

創建ConcurrentHashSet的代碼示例:

ConcurrentHashMap&ltString,Integer> certificationCosts = new ConcurrentHashMap<>(); 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()。

技術分享圖片

從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中創建線程安全的ConcurrentHashSet