在我的應用程序中,我將使用Map。如果多個線程寫入單個映射,則使用哪個映射實現
- 多個線程將寫入數據到這張地圖。寫操作太多了。
- 但是,在每次寫入期間,提供給映射的數據都有不同的鍵。
- 地圖中的數據不會在應用程序的任何位置讀取。
- 有一段時間,內容將被轉儲到一個文件。
我想了解以下內容:
- 在這種情況下,有必要同步寫入方法?
- ConcurrentHashMap是否適合我的需求?
- 如果不是,那麼 這個案例中正確的Map實現將使用什麼?
在我的應用程序中,我將使用Map。如果多個線程寫入單個映射,則使用哪個映射實現
我想了解以下內容:
關注以下幾點:
被饋送到地圖中的數據具有不同的密鑰在每次寫入
在地圖中的數據將不會在任何時候讀在應用
你並不需要一個Map
在所有。我假設,當你聲明地圖中的數據不會被讀取時,你的意思是你沒有做map.get(someKey)
,而是你將遍歷整個地圖以將數據存儲在文件中(或者任何數據源使用)。
這一點:
- 在一段時間後的內容將被轉儲到一個文件
加強上述建議。
着眼於這一點:
- 多個線程將數據寫入到這個map.The寫操作太多。
最好的建議是使用BlockingQueue
。作爲實施,您可以使用LinkedBlockingQueue
。
如果您使用Java同步從Map
轉儲數據並且想要/需要以Map
的形式恢復此數據,請使用ConcurrentHashMap
。如果這不是您的用例的一部分,因爲您將以其他方式從文件中讀取數據,請避免使用Map
並使用BlockingQueue
。
如果您真的需要Map
,您需要的是ConcurrentHashMap
。詳細瞭解它here。
正如你也說:ConcurrentHashMap的似乎符合您的要求。它是線程安全的,無需同步整個地圖。讀取可以非常快速地進行,而寫入是通過鎖定完成的。
所有你的鑰匙都是獨一無二的,所以你不一定需要確保地圖的完整性,同步但你需要它的時候,你實際上將被寫入文件。使用ConccurentHashMap或正常的同步映射都適合你。您可以在沒有Map的情況下將鍵/值存儲在某個對象中,並將該對象存儲在同步列表中。
擁有不同的密鑰決不意味着寫入映射不需要同步。 –
來自例如['TreeMap'的Javadoc](https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html):*如果多個線程同時訪問地圖,並且至少有一個線程在結構上修改了地圖,它必須在外部同步*。 – Turing85
@JohnBollinger和圖靈:是的,我明白這一點。我的問題是,如果所有將要插入的鍵都是唯一的,並且地圖僅用於書寫目的,那麼可能的危害是什麼?例如:從一個線程寫入可能不會提供給另一個線程..足夠公平..當你寫入文件時唯一的危害是你可能看不到所有的更新..正確嗎?我錯過了什麼 ?我同意上面不是一個完美的評論 – Geek
但是我覺得這是一個矛盾:
你怎麼可以轉儲到一個文件中不讀呢?
我認爲這是肯定地說,ConcurrentHashMap的反正可以處理這種情況,所以要爲它。
一些解釋會很好,而不是簡單地說「是」或「否」。 – Turing85
爲1:Map
接口不保證任何同步,尤其是不寫。綜觀非併發實現(HashMap
,HashTable
,IdentityHashMap
,LinkedHashMap
,TreeMap
和WeakHashMap
),則所有狀態
如果多個線程同時訪問一個映射,並且線程中的至少一個修改了該映射結構,它必須在外部同步。
到2和3:如果您使用的是ConcurrentHashMap
,則不必擔心同步。但我同意Luiggi Mendoza's answer:不要使用Map
。
_「在地圖中的數據不會在應用程序的任何點讀」 _再_「在一段時間後的內容會被傾倒到一個文件」 _ - 你怎麼這麼轉儲到一個文件,而不閱讀地圖? –
這兩點是不兼容的:「地圖中的數據不會在應用程序的任何位置讀取」和「偶爾會將內容轉儲到文件中」。沒有讀出地圖的全部內容,內容不能轉儲到文件中。 –
您可能還想考慮爲每個線程保留一個映射,然後在轉儲到文件時合併它們。然後,只有在轉儲到文件時,纔會阻止對地圖的訪問,而不是爲每次寫入都阻止。 – xp500