日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯網營銷解決方案
不要在線上濫用CopyOnWriteArrayList,姿勢不對性能真的很糟糕

從JDK1.5版本,JAVA提供了線程安全的List增強版CopyOnWriteArrayList,其保持線程安全的方式是:每次修改數據時,不會直接修改數據,而是把數據復制出來一份,對復制出來的數組進行操作。

通過這樣的機制,可以極大程度的提升讀的并發(fā)性能,所以對于CopyOnWriteArrayList來說,非常適合讀多寫少或者無鎖的場景。

但是,如果我們?yōu)榱遂偶级环謭龊蠟E用CopyOnWriteArrayList的話,可能會帶來適得其反的結果。

下面,我們通過一段測試代碼,比較一下CopyOnWriteArrayList和普通加鎖ArrayList的讀寫性能差距。

我們首先測試一下寫性能的差距:構建一個CopyOnWriteArrayList和synchronizedList,通過多線程并發(fā)寫入100000個元素。

List copyOnWriteArrayList = new CopyOnWriteArrayList<>();
//構建一個加鎖的List
List synchronizedList = Collections.synchronizedList(new ArrayList<>());
StopWatch stopWatch = new StopWatch();
int loopCount = 100000;
stopWatch.start("測試寫性能:copyOnWriteArrayList");
//多線程寫入100000個數字
IntStream.rangeClosed(1, loopCount).parallel()
.forEach(x -> copyOnWriteArrayList.add(ThreadLocalRandom.current().nextInt(loopCount))
);
stopWatch.stop();
stopWatch.start("測試寫性能:synchronizedList");
//多線程寫入100000個數字
IntStream.rangeClosed(1, loopCount).parallel()
.forEach(x -> synchronizedList.add(ThreadLocalRandom.current().nextInt(loopCount))
);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
Map result = new HashMap<>();
result.put("copyOnWriteArrayList", copyOnWriteArrayList.size());
result.put("synchronizedList", synchronizedList.size());
System.out.println(JSON.toJSONString(result));

可以清楚的看到,在大量寫的情況下,CopyOnWriteArrayList的性能是遠遠不如普通的加鎖List的,性能差距可能在100倍以上。

而之所以CopyOnWriteArrayList的寫入這么慢,就是因為CopyOnWriteArrayList每次寫入都要對存放元素的舊數組進行復制創(chuàng)建一個新數組,從而導致內存申請釋放消耗很大。

我們再測試一下大量讀的性能差距:先對兩個List寫入100000個元素,再通過多線程的方式隨機get元素。

List synchronizedList = Collections.synchronizedList(new ArrayList<>());
synchronizedList.addAll(IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList()));

List copyOnWriteArrayList = IntStream.rangeClosed(1, 100000).boxed()
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));

StopWatch stopWatch = new StopWatch();
int loopCount = 1000000;
int count = copyOnWriteArrayList.size();
stopWatch.start("測試讀性能:copyOnWriteArrayList");
IntStream.rangeClosed(1, loopCount).parallel().forEach(
x -> copyOnWriteArrayList.get(ThreadLocalRandom.current().nextInt(count))
);
stopWatch.stop();
stopWatch.start("測試讀性能:synchronizedList");
IntStream.range(0, loopCount).parallel().forEach(
x -> synchronizedList.get(ThreadLocalRandom.current().nextInt(count))
);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
Map result = new HashMap<>();
result.put("copyOnWriteArrayList", copyOnWriteArrayList.size());
result.put("synchronizedList", synchronizedList.size());
System.out.println(JSON.toJSONString(result));

經過多次測試,CopyOnWriteArrayList的讀性能大概在普通加鎖List的2-5倍左右。

而CopyOnWriteArrayList的讀之所以快,是因為CopyOnWriteArrayList讀取元素是無鎖狀態(tài)下直接按數組下標獲取。

一般來說,CopyOnWriteArrayList只適用于大量讀的場景,如果有了大量寫操作,性能反而不如普通的List。

JDK為我們提供了很多用于并發(fā)場景的工具類,但是仍需要我們仔細了解每一種工具的使用場景,在不合適的場景使用不合適的工具,會導致性能更差。


分享標題:不要在線上濫用CopyOnWriteArrayList,姿勢不對性能真的很糟糕
URL地址:http://www.dlmjj.cn/article/cdschgs.html