2010-05-14 13 views
43

जावा में ConcurrentHashMap का उपयोग क्या है? इसके फायदे क्या हैं? यह कैसे काम करता है? नमूना कोड भी उपयोगी होगा।जावा में ConcurrentHashMap?

+0

उपयोगी http://javarevisited.blogspot.in/2013/02/concurrenthashmap-in-java-example-tutorial-working.html – roottraveller

उत्तर

58

बिंदु HashMap का कार्यान्वयन प्रदान करना है जो थ्रेडसेफ है। कई धागे पढ़ सकते हैं और बिना किसी तारीख या दूषित डेटा प्राप्त करने के मौके के बिना इसे लिख सकते हैं। ConcurrentHashMap अपने स्वयं के सिंक्रनाइज़ेशन प्रदान करता है, इसलिए आपको इसे स्पष्ट रूप से एक्सेस सिंक्रनाइज़ करने की आवश्यकता नहीं है।

ConcurrentHashMap की एक अन्य विशेषता यह putIfAbsent विधि है, जो atomically यदि निर्दिष्ट कुंजी मौजूद नहीं है एक मानचित्रण जोड़ देगा प्रदान करता है। क्योंकि एक और धागा contains करने के लिए कॉल और put करने के लिए कॉल के बीच "key" के लिए एक मानचित्रण जोड़ सकता है,

ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>(); 

// some stuff 

if (!myMap.contains("key")) { 
    myMap.put("key", 3); 
} 

इस कोड threadsafe नहीं है: निम्नलिखित कोड पर विचार करें। सही कार्यान्वयन होगा:

myMap.putIfAbsent("key", 3); 
+4

मैं इसे "सुरक्षित रूप से अनसंक्रनाइज़" के रूप में वर्णित करता हूं। यह दो धागे एक ही समय में मकिंग के अंदर होने की अनुमति देता है और बाद में एक सतत राज्य में समाप्त होने का वादा करता है। – Affe

+4

सिंक्रनाइज़ेशन एक (बाहरी) ऑर्डरिंग गारंटी नहीं है। – danben

+4

यह गारंटी नहीं है कि मॉनिटर का अनुरोध करने वाले धागे इसे अनुरोधित आदेश में प्राप्त करेंगे, लेकिन यह एक गारंटी से पहले होता है कि एक बार थ्रेड मॉनिटर प्राप्त करता है और मानचित्र को संशोधित करना शुरू करता है, संशोधन में कोई और इसे तब तक नहीं देख पाएगा किया हुआ। समवर्ती मानचित्र में एक थ्रेड एक पुट शुरू कर सकता है, फिर लंबे समय तक फिर से निर्धारित नहीं किया जा सकता है और अन्य धागे निष्पादित हो सकते हैं जो प्रगति में नहीं दिखेंगे। – Affe

11

सच बड़ा कार्यात्मक अंतर यह एक अपवाद फेंक नहीं है और/या जब किसी और यह परिवर्तन आप इसे प्रयोग कर रहे हैं, जबकि भ्रष्ट में पहुंचते हैं।

नियमित संग्रह के साथ, यदि कोई अन्य धागा किसी तत्व को जोड़ता है या हटा देता है, तो आप इसे एक्सेस करते हैं (इटरेटर के माध्यम से) यह अपवाद फेंक देगा। ConcurrentHashMap उन्हें परिवर्तन करने देता है और आपके धागे को रोकता नहीं है।

आपको लगता है कि यह किसी भी प्रकार की सिंक्रनाइज़ेशन गारंटी या एक धागे से दूसरे में परिवर्तन की बिंदु-समय-समय दृश्यता के बारे में वादा नहीं करता है। (यह एक सिंक्रनाइज़ किए गए डेटाबेस अलगाव की तरह है, जो एक सिंक्रनाइज़ किए गए डेटाबेस अलगाव की तरह व्यवहार करता है। (पुराने स्कूल पंक्ति-लॉकिंग एसक्यूएल सीरियलज़ेबल, ओरेकल-आईएसएच मल्टीवर्सन सीरियलज़ेबल नहीं है :))

सबसे अधिक आम तौर पर मुझे पता है कि ऐप सर्वर वातावरण में अपरिवर्तनीय व्युत्पन्न जानकारी कैशिंग में है जहां कई धागे एक ही चीज़ तक पहुंच सकते हैं, और इससे कोई फर्क नहीं पड़ता कि दो कैश वैल्यू की गणना करने के लिए क्या होता है और इसे दो बार डाल दिया जाता है क्योंकि वे इंटरलीव करते हैं, आदि (उदाहरण के लिए, यह रनटाइम-व्युत्पन्न कॉन्फ़िगरेशन को यूआरएल से हैंडलर तरीके से मैपिंग जैसे स्प्रिंग वेबएमवीसी ढांचे के अंदर बड़े पैमाने पर उपयोग किया जाता है।)

+1

यह बिल्कुल सही नहीं है। जावाडॉक्स स्पष्ट रूप से निर्दिष्ट करते हैं कि सभी परिचालन थ्रेडसेफ हैं। – danben

+0

सभी ऑपरेशन थ्रेडसेफ हैं, लेकिन सिंक्रनाइज़ किए गए मानचित्र के साथ वादे होने से पहले ऐसा नहीं होता है। जब आप ConcurrentHashMap में देखते हैं तो आप जो देखते हैं वह सबसे हाल ही में किए गए परिचालनों का परिणाम है। जब आप देखना चाहते हैं तो कुछ समय बाद में काफी समय से शुरू हो सकते हैं। यह एक पठित डेटाबेस पृथक्करण की तरह काम करता है, जबकि एक सिंक्रनाइज़ नक्शा एक serializable डेटाबेस अलगाव की तरह काम करता है। – Affe

+0

उत्कृष्ट उत्तर – SuprF1y

22

ConcurrentHashMap मानचित्र पर समवर्ती पहुंच की अनुमति देता है। हैशटेबल भी मानचित्र पर सिंक्रनाइज़ पहुंच प्रदान करता है, लेकिन आपका पूरा नक्शा किसी भी ऑपरेशन को करने के लिए बंद कर दिया गया है।

ConcurrentHashMap के पीछे तर्क your entire table is not getting locked है, लेकिन केवल भाग [segments] है। प्रत्येक सेगमेंट अपने ही हैशटेबल का प्रबंधन करता है। लॉकिंग केवल अपडेट के लिए लागू होती है। पुनर्प्राप्ति के मामले में, यह पूर्ण सहमति प्रदान करता है।

चलो चार धागे एक मानचित्र पर एक साथ काम कर रहे हैं जिनकी क्षमता 32 है, तालिका को चार खंडों में विभाजित किया गया है जहां प्रत्येक सेगमेंट क्षमता की हैश तालिका का प्रबंधन करता है। संग्रह डिफ़ॉल्ट रूप से 16 सेगमेंट की एक सूची बनाए रखता है, जिनमें से प्रत्येक मानचित्र के एक बाल्टी को सुरक्षित (या लॉक) करने के लिए उपयोग किया जाता है।

enter image description here

यह प्रभावी रूप से इसका मतलब है कि 16 धागे से एक बार में संग्रह संशोधित कर सकते हैं। वैकल्पिक समवर्तीकरणवेल कन्स्ट्रक्टर तर्क का उपयोग करके समेकन का यह स्तर बढ़ाया जा सकता है।

public ConcurrentHashMap(int initialCapacity, 
         float loadFactor, int concurrencyLevel) 

अन्य जवाब के रूप में कहा गया है, ConcurrentHashMap नई विधि putIfAbsent() जो मूल्य को छोड़कर डाल करने के लिए इसी तरह की है अगर कुंजी मौजूद है अधिरोहित नहीं किया जाएगा प्रदान करता है।

private static Map<String,String> aMap =new ConcurrentHashMap<String,String>(); 

if(!aMap.contains("key")) 
    aMap.put("key","value"); 

नई विधि भी तेजी के रूप में यह double traversing के रूप में ऊपर से बचा जाता है है। contains विधि को सेगमेंट का पता लगाने और कुंजी को खोजने के लिए टेबल को फिर से चालू करना है और फिर विधि put को बाल्टी को पार करना और कुंजी रखना है।

+0

डिफ़ॉल्ट आकार से 32 है, तो कैसे 4 धागे आकार 16 के खंड बना सकते हैं। यह 8 नहीं होगा –

2

यह Memoization के लिए इस्तेमाल किया जा सकता है:

import java.util.concurrent.ConcurrentHashMap; 
public static Function<Integer, Integer> fib = (n) -> { 
    Map<Integer, Integer> cache = new ConcurrentHashMap<>(); 
    if (n == 0 || n == 1) return n; 
    return cache.computeIfAbsent(n, (key) -> HelloWorld.fib.apply(n - 2) + HelloWorld.fib.apply(n - 1)); 
}; 
0

1.ConcurrentHashMap धागा सुरक्षित है कि है कोड एक समय में एकल थ्रेड द्वारा पहुँचा जा सकता है।

2.ConcurrentHashMap मानचित्र के कुछ हिस्सों पर सिंक्रनाइज़ या ताले लगाता है। ConcurrentHashMap के प्रदर्शन को अनुकूलित करने के लिए, मानचित्र को Concurrency स्तर के आधार पर विभिन्न विभाजनों में विभाजित किया गया है। इसलिए हमें पूरे मानचित्र ऑब्जेक्ट को सिंक्रनाइज़ करने की आवश्यकता नहीं है।

3. डिफॉल्ट समेकन स्तर 16 है, तदनुसार नक्शा 16 भाग में बांटा गया है और प्रत्येक भाग को एक अलग लॉक के साथ शासित किया जाता है जिसका अर्थ है कि 16 धागा संचालित हो सकता है।

4.ConcurrentHashMap पूर्ण मूल्यों की अनुमति नहीं देता है। तो कुंजी ConcurrentHashMap में शून्य नहीं हो सकता है।

संबंधित मुद्दे