[英]Which Java Collections are synchronized(thread safe), which are not?
哪些 Java 集合是同步的,哪些不是?
示例:HashSet 不同步
共有三組集合。
Collections.synchronizedXxx()
方法進行同步簡而言之,我建議您使用的所有集合都不是同步的。
線程安全集合 -
線程安全,無需同步整個地圖 使用鎖完成寫入時讀取速度非常快 在對象級別沒有鎖定 使用多個鎖。
對象級同步 讀寫都獲取鎖 鎖定集合有性能缺陷 可能導致爭用
向量
哈希表
復制寫入數組列表
復制寫入數組集
堆
其余的都不是線程安全的
簡單回答:沒有一個Collection
實現是同步的,因為synchronized
不是類屬性,它只適用於方法和塊。
我想,您想知道哪些實現是線程安全的,哪些來自 java 集合框架的類可以安全地用於多線程環境中。
該信息始終包含在 javadoc 中( 例如:Arraylist - 這不是線程安全的)
Collection 接口中的ArrayList、LinkedList、HashSet、LinkedHashset 和TreeSet 以及HashMap、LinkedHashMap 和Treemap 都是非同步的。
集合接口中的向量是同步的
前面的例子是完全錯誤的。
首先,您沒有從不同的線程訪問您剛剛同步的列表,您無法證明同步正在正確執行,您無法證明添加過程是原子的。 其次,列表本身上的同步子句是一種不好的做法,您不知道優化器是否會使用列表中的項目進行同步,從而導致意外行為。 此外,您正在同步的是對列表中元素的讀取/寫入訪問,而不是列表本身。 取出 Collections.synchronized 並查看輸出。 多試幾次。 請舉以下例子:
class ProcessSomething {
private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
private void calculate() {
for (int i = 0; i < 10000; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
integerList.add(new Random().nextInt(100));
}
}
private void calculate2() {
for (int i = 0; i < 10000; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
integerList.add(new Random().nextInt(100));
}
}
public void process() {
Long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable() {
public void run() {
calculate();
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
calculate2();
}
});
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException ex) {
Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
}
Long end = System.currentTimeMillis();
System.out.println("Duration: " + (end - start));
System.out.println("List size: " + integerList.size());
}
}
public class App {
public static void main(String[] args) {
new ProcessSomething().process();
}
}
java.util 包中的所有集合類(Vector 和Hashtable 除外)都不是線程安全的。 僅有的兩個遺留集合是線程安全的:Vector 和 Hashtable。 為什么? 原因如下:同步可能非常昂貴! 你知道,Vector 和 Hashtable 是 Java 歷史早期存在的兩個集合,它們從一開始就是為線程安全而設計的(如果你有機會查看它們的源代碼,你會發現它們的方法都是同步的!)。 然而,它們很快暴露了多線程程序的性能不佳。 您可能知道,同步需要鎖,這總是需要時間來監控,這會降低性能。 這就是新集合(List、Set、Map 等)根本不提供並發控制以在單線程應用程序中提供最大性能的原因。
同步使性能降低。 當然,Java集合不是同步的。 但是 Java 提供了一個 Synchronization Wrappers 來同步 Java Collection 見鏈接
for example:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class SynchronizedListExample {
public static void main(String[] args) {
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
syncList.add("one");//no need to synchronize here
syncList.add("two");
syncList.add("three");
String st = syncList.get(0); //it is ok here => no need to synchronize
// when iterating over a synchronized list, we need to synchronize access to the synchronized list
//because if you don't synchronize here, synchList maybe be changed during iterating over it
synchronized (syncList) {
Iterator<String> iterator = syncList.iterator();
while (iterator.hasNext()) {
System.out.println("item: " + iterator.next());
}
}
}
}
導入 java.util.Collections; //導入這個
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
這就是您如何在 Java 中同步列表。
線程安全集合
Vector
(父級為List
)和Hashtable
(父級為Map
)synchronized
監視器。 Collections.synchronized
, Collections.synchronizedList()
, Collections.synchronizedSortedMap()
, Collections.synchronizedSet()
...Copy-On-Write(COW)
- 比同步集合具有更好的性能,但具有更大的內存占用。 修改數組時會創建新的數組副本(添加、設置、刪除)。 它是多讀操作和后修改的一個很好的變體。 CopyOnWriteArrayList
, CopyOnWriteArraySet
Compare-And-Swap(CAS)
[關於] - ConcurrentLinkedQueue
, ConcurrentSkipListMap
Lock
- ConcurrentHashMap
, BlockingQueue
后代我猜集合 API 的每個實現都寫在文檔中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.