【JAVA】CopyOnWrite的使用

好久沒寫文章了,最近有種深深的危機感,準備打打雞血,溫故以前看過但是工作中很少用到的知識點。

 

CopyOnWrite寫時複製,JDK中一共有兩個類CopyOnWriteArrayList和CopyOnWriteArraySet。

顧名思義,就是隻有容器中內容被修改的時候,就會copy出一個容器,然後在這個新的容器裏改,之後將原容器的引用指向這個新的容器;好處就是對這個容器進行併發讀寫操作的時候,不需要額外加鎖。

從以上源碼看到,讀的時候,並沒有加鎖,讀的是原容器的數據,所以當正在寫入的時候,讀的可能是舊數據。

以上這種,本人在實際項目中的確使用過,但是並沒有使用CopyOnWrite,而是自己通過加鎖來實現的,大家看以下代碼:

public static volatile Map<String, String> MAP_URL = new HashMap<String, String>();
public void urlRefresh() {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		// paramMap.put(MapUrlMapper.id, "");
		List<MapUrl> list = mapUrlMapper.find(paramMap);
		if (list != null && list.size() > 0) {
			Map<String, String> tempUrl = new HashMap<String, String>();
			for (MapUrl mu : list) {
				String orderSyncKey = Constants.MAP_URL_PREFIX_ORDER_SYNC + mu.getAreaCoding();
				String memberSyncKey = Constants.MAP_URL_PREFIX_MEMBER_SYNC + mu.getAreaCoding();
				String yunwifiOnoffSyncKey = Constants.MAP_URL_PREFIX_YUN_WIFI_ONOFF_SYNC + mu.getAreaCoding();
				String orderSyncUrl = mu.getOpenInformationUrl();
				String memberSyncUrl = mu.getMemberSyncUrl();
				String yunwifiOnoffSyncUrl = mu.getWifiOnoffUrl();
				if (StringUtils.isNotEmpty(orderSyncUrl)) {
					tempUrl.put(orderSyncKey, orderSyncUrl);
				}
				if (StringUtils.isNotEmpty(memberSyncUrl)) {
					tempUrl.put(memberSyncKey, memberSyncUrl);
				}
				if (StringUtils.isNotEmpty(yunwifiOnoffSyncUrl)) {
					tempUrl.put(yunwifiOnoffSyncKey, yunwifiOnoffSyncUrl);
				}
			}
			OverAllVar.MAP_URL = tempUrl;
			logger.info("刷新URL數據 {}", OverAllVar.MAP_URL);
		} else {
			OverAllVar.MAP_URL.clear();
		}
	}

可以看到,作用和CopyOnWrite是一樣的。

 

使用CopyOnWrite因爲存在數據的複製,必然會導致內存佔用增加,增加GC的次數,所以大家在使用時酌情考慮。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章