Java में ConcurrentHashMap?




(4)

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


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

ConcurrentHashMap की एक और विशेषता यह है कि यह putIfAbsent विधि प्रदान करता है, जो कि निर्दिष्ट कुंजी मौजूद नहीं होने पर एक मानचित्रण को putIfAbsent रूप से जोड़ देगा। निम्नलिखित कोड पर विचार करें:

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

// some stuff

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

यह कोड थ्रेडसेफ़ नहीं है, क्योंकि किसी अन्य थ्रेड में कॉल करने और कॉल करने के लिए "key" लिए मैपिंग जोड़ सकता है। सही कार्यान्वयन होगा:

myMap.putIfAbsent("key", 3);

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

2.ConcurrentHashMap मैप के निश्चित भाग पर सिंक्रनाइज़ या लॉक करता है। ConcurrentHashMap के प्रदर्शन का अनुकूलन करने के लिए, मैप को अलग-अलग विभाजनों में विभाजित किया गया है, जो कि कंजेंसी के स्तर पर निर्भर करता है। ताकि हमें पूरी Map Object को सिंक्रोनाइज़ करने की जरूरत न पड़े।

3.Default concurrency level 16 है, तदनुसार मैप को 16 भाग में विभाजित किया गया है और प्रत्येक भाग को एक अलग लॉक से नियंत्रित किया गया है जिसका अर्थ है कि 16 थ्रेड संचालित हो सकते हैं।

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


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

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

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

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


इसका उपयोग संस्मरण के लिए किया जा सकता है:

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));
};




concurrenthashmap