淺析Java如何在并發(fā)環(huán)境下生成一個只讀的map
前言
在日常開發(fā)過程中,我們經(jīng)常會遇到一些資源初始化的情況,往往有些資源就是那種我初始化以后我們就不希望被改動,但是我們又擔心別人使用的時候不小心改動了,這時候我就在想,要是我們的JDK能提供一種不能被修改的容器改有多好,好死不死,jdk中還真有這樣的容器,map和list都有,這里以map為例子給大家講解一下!
一般用法
在項目中一些不被改變的資源,通常采用靜態(tài)代碼塊的形式去初始化,如下:
private static Map<Integer, String> readOnlyMap; static { Map<Integer, String> callTimesMap = new HashMap<>(); callTimesMap.put(1, "一呼"); callTimesMap.put(2, "二呼"); callTimesMap.put(3, "三呼"); callTimesMap.put(4, "四呼"); callTimesMap.put(5, "五呼"); callTimesMap.put(6, "六呼"); callTimesMap.put(7, "七呼"); callTimesMap.put(8, "八呼"); callTimesMap.put(9, "九呼"); callTimesMap.put(10, "十呼"); readOnlyMap = Collections.unmodifiableMap(callTimesMap); }
練習時長兩年半左右的Java練習生應該知道,這樣做的好處是由靜態(tài)代碼塊在Java虛擬機中的執(zhí)行時機所決定的,下面給大伙呱唧一下!
靜態(tài)代碼塊在Java中如何執(zhí)行
在Java中,靜態(tài)代碼塊由類加載器在加載類的過程中執(zhí)行。當類被第一次加載時,類加載器會執(zhí)行其中的靜態(tài)代碼塊,并且只會執(zhí)行一次。
創(chuàng)建只讀的容器
要創(chuàng)建只讀的容器其實也很簡單:
Collections.unmodifiableMap(callTimesMap);
這樣就可以實現(xiàn)了!
測試證明
public static void main(String[] args) { //模擬并發(fā)環(huán)境 new Thread(()->{ readOnlyMap.put(11,"s"); }).start(); readOnlyMap.put(11,"s"); }
測試結(jié)果:
Exception in thread "Thread-0" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableMap.put(Collections.java:1459)
at com.zhuiyi.yicall.callout.statistic.impl.SessionStatisticServiceImpl.lambda$main$0(SessionStatisticServiceImpl.java:94)
at java.lang.Thread.run(Thread.java:748)
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableMap.put(Collections.java:1459)
at com.zhuiyi.yicall.callout.statistic.impl.SessionStatisticServiceImpl.main(SessionStatisticServiceImpl.java:96)
我們可以看到“Thread-0”和"main"線程都拋出了異常!這說明在并發(fā)條件下確實不允許寫,只允許讀!
只讀容器的底層實現(xiàn)原理
直接上源碼:
private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable { private static final long serialVersionUID = -1034234728574286014L; private final Map<? extends K, ? extends V> m; UnmodifiableMap(Map<? extends K, ? extends V> m) { if (m==null) throw new NullPointerException(); this.m = m; } public int size() {return m.size();} public boolean isEmpty() {return m.isEmpty();} public boolean containsKey(Object key) {return m.containsKey(key);} public boolean containsValue(Object val) {return m.containsValue(val);} public V get(Object key) {return m.get(key);} public V put(K key, V value) { throw new UnsupportedOperationException(); } public V remove(Object key) { throw new UnsupportedOperationException(); } public void putAll(Map<? extends K, ? extends V> m) { throw new UnsupportedOperationException(); } public void clear() { throw new UnsupportedOperationException(); } //.....此處省略很多代碼 }
從源碼中我們可以看出,UnmodifiableMap實現(xiàn)了map接口,所以它具有map的所有功能,同時最最重要的是他將所有會動到容器中的數(shù)據(jù)的方法都拋出異常了!
如下:
public V put(K key, V value) { throw new UnsupportedOperationException(); } public V remove(Object key) { throw new UnsupportedOperationException(); } public void putAll(Map<? extends K, ? extends V> m) { throw new UnsupportedOperationException(); } public void clear() { throw new UnsupportedOperationException(); }
這樣就從源頭上控制了容器不支持寫,只支持讀!
思考:針對這樣的場景,是否還有別的實現(xiàn)方式?
答案肯定是有的,我們可以使用一個全局鎖,或者分布式鎖都能實現(xiàn)!
全局讀鎖:
ReadWriteLock lock = new ReentrantReadWriteLock(); public void readData() { lock.readLock().lock(); try { // 執(zhí)行讀取操作callTimesMap } finally { lock.readLock().unlock(); } }
如果使用分布式鎖或者全局鎖的話性能會變差,所以最好的解決方案就是直接創(chuàng)建一個不能被修改的容器,這樣效率是最高,也是最安全的!
到此這篇關(guān)于淺析Java如何在并發(fā)環(huán)境下生成一個只讀的map的文章就介紹到這了,更多相關(guān)Java并發(fā)生成只讀map內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+netty-socketio實現(xiàn)服務(wù)器端消息推送
這篇文章主要介紹了SpringBoot+netty-socketio實現(xiàn)服務(wù)器端消息推送,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03Java實現(xiàn)將PDF轉(zhuǎn)為PDF/A
通過將PDF格式轉(zhuǎn)換為PDF/A格式,可保護文檔布局、格式、字體、大小等不受更改,從而實現(xiàn)文檔安全保護的目的,同時又能保證文檔可讀、可訪問。本文將為大家介紹如何實現(xiàn)這一轉(zhuǎn)換,需要的可以參考一下2022-01-01詳解Java設(shè)計模式編程中的Flyweight享元模式的開發(fā)結(jié)構(gòu)
這篇文章主要介紹了Java設(shè)計模式編程中的Flyweight享元模式的開發(fā)結(jié)構(gòu),享元模式能夠最大限度地重用現(xiàn)有的同類對象,需要的朋友可以參考下2016-04-04淺談synchronized方法對非synchronized方法的影響
下面小編就為大家?guī)硪黄獪\談synchronized方法對非synchronized方法的影響。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10java控制臺實現(xiàn)學生信息管理系統(tǒng)(IO版)
這篇文章主要為大家詳細介紹了java控制臺實現(xiàn)學生信息管理系統(tǒng)(IO版),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-04-04