2013-11-25 4 views
5

मैं अपने ServletContext में एक हैश मैप ऑब्जेक्ट संग्रहीत कर रहा हूं। लेकिन एकाधिक अनुरोध धागा पढ़ रहे हैं और इस हैश मैप को संशोधित कर रहे हैं।ServletContext ऑब्जेक्ट्स की थ्रेड सुरक्षा

जैसा कि मैं विश्वास करता हूं कि ServletContext ऑब्जेक्ट्स अनुरोध थ्रेड के बीच साझा किए जाते हैं, क्या मुझे इस हैश मैप तक पहुंच सिंक्रनाइज़ करने की आवश्यकता है? या क्या इसे प्राप्त करने के लिए कोई और बेहतर तरीका है?

+0

क्या आपने TreeMap को आजमाया था? – Prateek

+0

क्या आप अपना कोड डाल सकते हैं? –

उत्तर

10

ServletContext#setAttribute के माध्यम से प्रकाशन विशेषताओं थ्रेड-सुरक्षित है! यह जावा सर्वलेट विशिष्टता, अध्याय 4.5: (...) से प्राप्त किया जा सकता है किसी भी विशेषता किसी संदर्भ में किसी भी अन्य सर्वलेट के लिए उपलब्ध है जो उसी वेब एप्लिकेशन का हिस्सा है। (...)

(कारण: अन्य सर्लेट्स के लिए उपलब्ध वस्तुओं को बनाने का मतलब है कि उन्हें अन्य धागे के लिए भी उपलब्ध कराया जाए। यह केवल तभी संभव है जब उचित सिंक्रनाइज़ेशन का उपयोग किया जाए, इसलिए ServletContext#setAttribute के लिए सिंक्रनाइज़ेशन अनिवार्य है)।

तो ServletContext#getAttribute के माध्यम से प्रकाशित विशेषताओं को पढ़ने के लिए भी यही सच है।

लेकिन निश्चित रूप से अगर एक HashMap की तरह एक वस्तु अलग धागे के बीच साझा किया जाता है, डेवलपर सुनिश्चित करना चाहिए कि इस साझा वस्तु अपने आप में एक उचित, धागा सुरक्षित तरीके से एक्सेस किया जाता है!इसलिए

ConcurrentMap<String, Object> shared = (...)servletContext.getAttribute("sharedData"); 
if (shared == null) { 
    shared = new ConcurrentHashMap<>(); 
    servletContext.setAttribute("sharedData", shared); 
} 

, एक: एक ConcurrentHashMap के रूप में पहले से ही अपने प्रश्न का अन्य उत्तर में कहा गया है का उपयोग करना, एक संभव समाधान, के रूप में null जांच परमाणु नहीं होगा, लेकिन रेस स्थिति जब विशेषता आरंभ नहीं हो जाता समाधान नहीं करता है वेब अनुप्रयोग शुरू होने पर संदर्भ को आरंभ करने के लिए ServletContextListener का उपयोग किया जा सकता है!

1

एक बहुप्रचारित वातावरण में सबसे अच्छा तरीका java.util.concurrent.ConcurrentHashMap का उपयोग करना है। यह विशेष रूप से इस तरह से डिज़ाइन किया गया है जो आपको ConcurrentModificationException के बिना इसे पढ़ने और संशोधित करने की अनुमति देता है। फिर भी, पुनरावृत्ति के मामले में आपको पूर्वानुमानित परिणामों को हमेशा प्राप्त करने के लिए, इसके उदाहरण पर सिंक्रनाइज़ करना चाहिए।

संदर्भ पर सिंक्रनाइज़ करने से आपको बहुत सारे ओवरहेड मिलते हैं, यदि आप बहुमत वाले तरीके से वहां से कुछ और प्राप्त करते हैं। तो ConcurrentHashMap एक बेहतर समाधान है।

आप इसके बारे में यहाँ पढ़ सकते हैं:

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html

अद्यतन के लिए retrievals की पूर्ण संगामिति और समायोज्य उम्मीद संगामिति समर्थन एक हैश तालिका। पुनर्प्राप्ति संचालन (प्राप्त करने सहित) आम तौर पर ब्लॉक नहीं करते हैं, इसलिए अद्यतन संचालन (डाल और निकालने सहित) के साथ ओवरलैप हो सकता है।

-1

आपको अपनी ServletContext ऑब्जेक्ट को सिंक्रनाइज़ करने की आवश्यकता है। उदाहरण के लिए: -

synchronized(ctx){ 
//your code here 
} 
+0

एक सामान्य नियम के रूप में, आपको उस ऑब्जेक्ट के आंतरिक (मॉनिटर) लॉक का उपयोग नहीं करना चाहिए जिसे आप नियंत्रित नहीं करते हैं। – kbolino

2

@Artem Moskalev द्वारा सुझाए गए के रूप में, आप ConcurrentHashMap का उपयोग करें और सरल put विधि के बजाय वस्तु/मान संग्रहीत करने के लिए putIfAbsent विधि का उपयोग कर सकते हैं।

मैं इस टिप्पणी को @Artem Moskalev' के उत्तर से नीचे जोड़ना चाहता था लेकिन मेरे पास इसके लिए पर्याप्त प्रतिष्ठा नहीं है।

+0

कुछ प्रतिनिधि है। आप किसी भी समय टिप्पणी जोड़ने में सक्षम होंगे। :) –

0

हाँ, सुनिश्चित करें कि जब आप HashMap संशोधित करते हैं; यह सिंक्रनाइज़ या धागा सुरक्षित है।

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