जावा में, ConcurrentHashMap
बेहतर multithreading
समाधान के लिए है। फिर मुझे कब उपयोग करना चाहिए ConcurrentSkipListMap
? क्या यह अतिरेक है?
क्या इन दोनों के बीच बहुआयामी पहलू आम हैं?
जावा में, ConcurrentHashMap
बेहतर multithreading
समाधान के लिए है। फिर मुझे कब उपयोग करना चाहिए ConcurrentSkipListMap
? क्या यह अतिरेक है?
क्या इन दोनों के बीच बहुआयामी पहलू आम हैं?
जवाबों:
ये दोनों वर्ग कुछ मायनों में अलग-अलग हैं।
ConcurrentHashMap अपने अनुबंध के भाग के रूप में अपने संचालन के क्रम की गारंटी नहीं देता है। यह कुछ लोड फैक्टर के लिए ट्यूनिंग की अनुमति देता है (मोटे तौर पर, थ्रेड की संख्या समवर्ती इसे संशोधित करता है)।
दूसरी ओर, समवर्ती SipListMap , कई प्रकार के संचालन पर औसत O (लॉग (n)) प्रदर्शन की गारंटी देता है। यह भी संगामिति के लिए ट्यूनिंग का समर्थन नहीं करता है। ConcurrentSkipListMap
कई ऑपरेशन भी हैं जो ConcurrentHashMap
नहीं करते हैं: सीलिंगइंट्री / की, फ्लोरएंट्री / की, आदि। यह एक क्रमबद्ध क्रम भी रखता है, जिसे यदि आप उपयोग कर रहे हैं, तो अन्यथा गणना करना होगा (उल्लेखनीय खर्च पर) ConcurrentHashMap
।
मूल रूप से, विभिन्न उपयोग मामलों के लिए अलग-अलग कार्यान्वयन प्रदान किए जाते हैं। यदि आपको त्वरित एकल कुंजी / मान जोड़ी जोड़ और त्वरित एकल कुंजी लुकअप की आवश्यकता है, तो उपयोग करें HashMap
। यदि आपको तेज़-इन-ऑर्डर ट्रैवर्सल की आवश्यकता है, और प्रविष्टि के लिए अतिरिक्त लागत वहन कर सकते हैं, का उपयोग करें SkipListMap
।
* हालांकि मुझे उम्मीद है कि कार्यान्वयन ओ (1) सम्मिलन / देखने की सामान्य हैश-मैप गारंटी के अनुरूप है; फिर से हैशिंग की अनदेखी
डेटा संरचना की परिभाषा के लिए छोड़ें सूची देखें ।
इसकी कुंजी के प्राकृतिक क्रम में एक ConcurrentSkipListMap
स्टोर Map
(या आपके द्वारा परिभाषित कुछ अन्य महत्वपूर्ण आदेश)। तो यह धीमी होगा get
/ put
/ contains
एक से संचालन HashMap
, लेकिन इस की भरपाई के लिए यह समर्थन करता है SortedMap
, NavigableMap
और ConcurrentNavigableMap
इंटरफेस।
प्रदर्शन के संदर्भ में, skipList
जब मानचित्र के रूप में उपयोग किया जाता है - 10-20 गुना धीमा प्रतीत होता है। यहाँ मेरे परीक्षणों का परिणाम है (Java 1.8.0_102-b14, x32 जीतें)
Benchmark Mode Cnt Score Error Units
MyBenchmark.hasMap_get avgt 5 0.015 ? 0.001 s/op
MyBenchmark.hashMap_put avgt 5 0.029 ? 0.004 s/op
MyBenchmark.skipListMap_get avgt 5 0.312 ? 0.014 s/op
MyBenchmark.skipList_put avgt 5 0.351 ? 0.007 s/op
और इसके अतिरिक्त - उपयोग-मामला जहां एक-दूसरे की तुलना करना वास्तव में समझ में आता है। इन दोनों संग्रहों का उपयोग करके हाल ही में उपयोग की गई वस्तुओं के कैश का कार्यान्वयन। अब SkipList की दक्षता अधिक संदिग्ध होने लगती है।
MyBenchmark.hashMap_put1000_lru avgt 5 0.032 ? 0.001 s/op
MyBenchmark.skipListMap_put1000_lru avgt 5 3.332 ? 0.124 s/op
यहाँ JMH के लिए कोड है (के रूप में निष्पादित java -jar target/benchmarks.jar -bm avgt -f 1 -wi 5 -i 5 -t 1
)
static final int nCycles = 50000;
static final int nRep = 10;
static final int dataSize = nCycles / 4;
static final List<String> data = new ArrayList<>(nCycles);
static final Map<String,String> hmap4get = new ConcurrentHashMap<>(3000, 0.5f, 10);
static final Map<String,String> smap4get = new ConcurrentSkipListMap<>();
static {
// prepare data
List<String> values = new ArrayList<>(dataSize);
for( int i = 0; i < dataSize; i++ ) {
values.add(UUID.randomUUID().toString());
}
// rehash data for all cycles
for( int i = 0; i < nCycles; i++ ) {
data.add(values.get((int)(Math.random() * dataSize)));
}
// rehash data for all cycles
for( int i = 0; i < dataSize; i++ ) {
String value = data.get((int)(Math.random() * dataSize));
hmap4get.put(value, value);
smap4get.put(value, value);
}
}
@Benchmark
public void skipList_put() {
for( int n = 0; n < nRep; n++ ) {
Map<String,String> map = new ConcurrentSkipListMap<>();
for( int i = 0; i < nCycles; i++ ) {
String key = data.get(i);
map.put(key, key);
}
}
}
@Benchmark
public void skipListMap_get() {
for( int n = 0; n < nRep; n++ ) {
for( int i = 0; i < nCycles; i++ ) {
String key = data.get(i);
smap4get.get(key);
}
}
}
@Benchmark
public void hashMap_put() {
for( int n = 0; n < nRep; n++ ) {
Map<String,String> map = new ConcurrentHashMap<>(3000, 0.5f, 10);
for( int i = 0; i < nCycles; i++ ) {
String key = data.get(i);
map.put(key, key);
}
}
}
@Benchmark
public void hasMap_get() {
for( int n = 0; n < nRep; n++ ) {
for( int i = 0; i < nCycles; i++ ) {
String key = data.get(i);
hmap4get.get(key);
}
}
}
@Benchmark
public void skipListMap_put1000_lru() {
int sizeLimit = 1000;
for( int n = 0; n < nRep; n++ ) {
ConcurrentSkipListMap<String,String> map = new ConcurrentSkipListMap<>();
for( int i = 0; i < nCycles; i++ ) {
String key = data.get(i);
String oldValue = map.put(key, key);
if( (oldValue == null) && map.size() > sizeLimit ) {
// not real lru, but i care only about performance here
map.remove(map.firstKey());
}
}
}
}
@Benchmark
public void hashMap_put1000_lru() {
int sizeLimit = 1000;
Queue<String> lru = new ArrayBlockingQueue<>(sizeLimit + 50);
for( int n = 0; n < nRep; n++ ) {
Map<String,String> map = new ConcurrentHashMap<>(3000, 0.5f, 10);
lru.clear();
for( int i = 0; i < nCycles; i++ ) {
String key = data.get(i);
String oldValue = map.put(key, key);
if( (oldValue == null) && lru.size() > sizeLimit ) {
map.remove(lru.poll());
lru.add(key);
}
}
}
}
फिर मुझे समवर्ती SsipListMap का उपयोग कब करना चाहिए?
जब आपको (ए) कुंजी को क्रमबद्ध रखने की आवश्यकता होती है, और / या (बी) को एक नेविगेट करने योग्य नक्शे के पहले / अंतिम, सिर / पूंछ, और उपमैप सुविधाओं की आवश्यकता होती है।
ConcurrentHashMap
वर्ग को लागू करता है ConcurrentMap
इंटरफ़ेस, के रूप में करता है ConcurrentSkipListMap
। लेकिन अगर आप भी के व्यवहार चाहते हैं SortedMap
और NavigableMap
, का उपयोग करेंConcurrentSkipListMap
ConcurrentHashMap
ConcurrentSkipListMap
यहां सारणी Map
11 के साथ बंडल किए गए विभिन्न कार्यान्वयनों की प्रमुख विशेषताओं के माध्यम से तालिका आपको निर्देशित कर रही है । ज़ूम करने के लिए क्लिक / टैप करें।
ध्यान रखें कि आप अन्य Map
कार्यान्वयन प्राप्त कर सकते हैं , और इसी तरह की डेटा संरचनाएं, अन्य स्रोतों जैसे कि Google अमरूद से ।
String
सिर्फ एक अन्य वर्ग आरेख बनाया है ।
वर्कलोड के आधार पर समवर्ती SkipListMap रेंजफाइ की जरूरत पड़ने पर KAFKA-8802 में सिंक्रनाइज़ किए गए तरीकों के साथ TreeMap की तुलना में धीमा हो सकता है ।
समवर्ती हाशिए: जब आप चाहते हैं कि मल्टीथ्रेडेड इंडेक्स आधारित मिल / पुट हो, तो केवल इंडेक्स आधारित संचालन समर्थित हैं। Get / Put O (1) के हैं
ConcurrentSkipListMap: बस द्वारा संचालित / पुट की तुलना में अधिक संचालन, जैसे कुंजी द्वारा छांटे गए टॉप / बॉटम एन आइटम, अंतिम प्रविष्टि प्राप्त करना, कुंजी द्वारा छाँटे गए / पूरा नक्शा प्राप्त करना आदि जटिलता O (लॉग (n)) का है, इसलिए प्रदर्शन नहीं किया जाता है के रूप में महान समवर्ती HashMap। यह SkipList के साथ ConcurrentNavigableMap का कार्यान्वयन नहीं है।
जब आप मानचित्र पर अधिक संचालन करना चाहते हैं तो समवर्तीSkipListMap का उपयोग संक्षेप में करने के लिए केवल साधारण प्राप्त करने और डालने के बजाय छंटनी की आवश्यकता है।