小測試程序:
public class Test extends Thread {
public static void main(String[] args) throws Exception {
test(new Vector<>());
test(new ArrayList<>());
test(Collections.synchronizedList(new ArrayList<>()));
test(new CopyOnWriteArrayList<>());
}
private static void test(final List<Integer> list) throws Exception {
System.gc();
long start = System.currentTimeMillis();
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++)
threads[i] = new Test(list);
for (Thread thread : threads)
thread.start();
for (Thread thread : threads)
thread.join();
long end = System.currentTimeMillis();
System.out.println(list.size() + " in " + (end - start) + "ms using " + list.getClass().getSimpleName());
}
private final List<Integer> list;
Test(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
try {
for (int i = 0; i < 10000; i++)
this.list.add(i);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
樣本輸出
100000 in 16ms using Vector
java.lang.ArrayIndexOutOfBoundsException: 466
at java.util.ArrayList.add(ArrayList.java:459)
at Test.run(Test.java:36)
java.lang.ArrayIndexOutOfBoundsException: 465
at java.util.ArrayList.add(ArrayList.java:459)
at Test.run(Test.java:36)
java.lang.ArrayIndexOutOfBoundsException: 10
at java.util.ArrayList.add(ArrayList.java:459)
at Test.run(Test.java:36)
32507 in 15ms using ArrayList
100000 in 16ms using SynchronizedRandomAccessList
100000 in 3073ms using CopyOnWriteArrayList
正如你所看到的,與Vector
它正常完成並返回100000
,這是預期的大小後添加10個並行線程中的10000個值。
隨着ArrayList
你看到兩個不同的故障:
第三個測試,使用Collections.synchronizedList()
,就像Vector
一樣工作。
第四個測試,使用併發CopyOnWriteArrayList
,也會產生正確的結果,但由於過度複製,速度會更慢。但是,如果列表較小並且變化很少,但它會比同步訪問更快,但是經常讀取。
如果您需要迭代列表,這是非常好的,因爲即使Vector
和synchronizedList()
將與ConcurrentModificationException
一起失敗,如果迭代時修改列表,而CopyOnWriteArrayList
將迭代列表的快照。
出於好奇,我查了一些Deque
實現過:
test(new ArrayDeque<>());
test(new ConcurrentLinkedDeque<>());
test(new LinkedBlockingDeque<>());
樣本輸出
34295 in 0ms using ArrayDeque
100000 in 15ms using ConcurrentLinkedDeque
100000 in 16ms using LinkedBlockingDeque
正如你所看到的,不同步ArrayDeque
顯示 「貶值」症狀,儘管它不會失敗並帶有例外。
兩個併發的實現,ConcurrentLinkedDeque
和LinkedBlockingDeque
,工作良好且快速。
嘿,我試圖尋找它,但它一直帶我去不同的更有用的主題不是這樣基本的例子。 –
如果你想測試線程(聯合國)安全,你將不得不訪問/修改多個線程相同的集合。現在您正在創建2個矢量,並使用單個線程訪問每個矢量。 – Ma3x
對不起,我的錯誤讓我糾正和看到。 –