2012-05-07 11 views
14
डाल

जावा Docs का कहना है कि, putIfAbsentConcurrentHashMap बनाम putIfAbsent

if (!map.containsKey(key)) 
     return map.put(key, value); 
    else 
     return map.get(key); 

के बराबर है तो कुंजी के नक्शे में मौजूद रहने पर, यह अपने मूल्य अपडेट नहीं होता। क्या ये सही है?

यदि मैं कुछ मानदंडों के आधार पर एक कुंजी मान अपडेट करना चाहता हूं तो क्या होगा? समाप्ति समय आदि कहें

क्या यह कैश जोड़ने और अपडेट करने के लिए बेहतर प्रभाव होगा?

public void AddToCache(T key, V value) 
{ 
    V local = _cache.putifabsent(key, value); 

    if(local.equals(value) && local.IsExpired() == false){ 
    return; 
    } 
    // this is for updating the cache with a new value 
    _cache.put(key, value); 
} 
+0

@Gray दूसरी पंक्ति की तरह लग सकता है किया जाता है। कोड कह रहा है कि यदि कुंजी कैश में नहीं है, तो इसे डालें, अन्यथा केवल मान वापस करें। यदि कुंजी मान जोड़ी पहले से ही कैश में है तो यह मान अपडेट नहीं करता है। – DarthVader

+0

हालांकि आपका तर्क थोड़ा सा है। यदि 'स्थानीय'' मान' के बराबर है तो आपने अभी नक्शा अपडेट किया है। क्या आपका मतलब यह नहीं है कि यह * मूल्य * के बराबर नहीं है? मतलब मानचित्र में पहले से ही कुछ था? –

+0

ओह, मुझे खेद है, क्षमा करें। आप बनाने के लिए "अद्यतन" शब्द का उपयोग नहीं कर रहे हैं। तुम सही हो, क्षमा करें। – Gray

उत्तर

9

तो यह किसी कुंजी के मूल्य को अपडेट नहीं करता है। क्या ये सही है?

यह सही है। यह वर्तमान मूल्य वापस कर देगा जो पहले से ही मानचित्र में था।

क्या यह कैश जोड़ने और अपडेट करने के लिए बेहतर प्रभाव होगा?

कुछ चीजें आपके कार्यान्वयन को बेहतर बनाती हैं।

1. आप putIfAbsent उपयोग नहीं करना चाहिए यह मौजूद है, तो आप केवल यह प्रयोग करना चाहिए जब आप अगर एक तो putIfAbsent मौजूद नहीं है सुनिश्चित करना चाहते हैं परीक्षण करने के लिए। इसके बजाय आपको इसके अस्तित्व (या map.contains) का परीक्षण करने के लिए map.get का उपयोग करना चाहिए।

V local = _cache.get(key); 
    if (local.equals(value) && !local.IsExpired()) { 
     return; 
    } 

2. डाल आप बदलना चाहते जाएगा करने के बजाय, इस वजह से एक रेस स्थिति में हो सकता है जहां if दो या अधिक धागे से झूठे के रूप में मूल्यांकन किया जा सकता है, जिसमें दो में से एक (या अधिक) धागे अन्य धागे के रखरखाव को ओवरराइट करेंगे।

क्या आप के बजाय कर सकते हैं replace

जब सभी ने कहा और यह समतुल्य में इस

public void AddToCache(T key, V value) { 
    for (;;) { 

     V local = _cache.get(key); 
     if(local == null){ 
      local = _cache.putIfAbsent(key, value); 
      if(local == null) 
       return; 
     } 
     if (local.equals(value) && !local.IsExpired()) { 
      return; 
     } 

     if (_cache.replace(key, local, value)) 
      return; 
    } 
} 
+0

यदि प्रतिस्थापन() सही हो तो आपको वापस लौटना चाहिए। – jtahlborn

+0

@jtahlborn धन्यवाद ने अभी देखा है कि खुद को :) –

+0

भी, अगर आपको putIfAbsent() गैर-शून्य देता है, तो आपको फिर से कॉल करने की आवश्यकता नहीं है, आप जो भी प्राप्त कर सकते हैं उसका उपयोग कर सकते हैं। यदि प्रतिस्थापित विफल रहता है तो आपको केवल दूसरे प्राप्त() कॉल की आवश्यकता होती है। – jtahlborn

4

यदि आपका कोड मानचित्र में पहले नहीं था तो आपका कोड एनपीई फेंक देगा।

इसके अलावा, हालांकि यह एक उचित विचार है, यह "समवर्ती" वातावरण में काम नहीं करेगा। putIfAbsent() विधि को जोड़ा गया था ताकि नक्शा संचालन थ्रेड-सुरक्षित बनाने के लिए उपयोग किए जा रहे किसी भी अंतर्निहित समर्थन का उपयोग करके ऑपरेशन की परमाणुता का प्रबंधन कर सके। आपके कार्यान्वयन में, 2 अलग-अलग कॉलर एक-दूसरे पर कदम उठाने का अंत कर सकते हैं (पहले एक नए के साथ एक कालबाह्य मूल्य बदलता है, और दूसरा तुरंत दूसरे नए को एक दूसरे के साथ बदल देता है)।

+0

समवर्ती स्थिति के बारे में तथ्य अक्सर पर्याप्त रूप से इंगित नहीं किया जा सकता है। :) +1 – pimpf0r

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