2011-05-31 10 views
9

मुझे एक समवर्ती वातावरण में आलसी लोड संसाधनों की आवश्यकता है। संसाधनों को लोड करने के लिए कोड केवल एक बार निष्पादित किया जाना चाहिए।आलसी लोडेड सिंगलटन: डबल-चेक लॉकिंग बनाम मांग धारक idiom पर प्रारंभिक

Double-checked locking (जेआरई 5+ और अस्थिर कीवर्ड का उपयोग करके) और Initialization on demand holder idiom अच्छी तरह से नौकरी के लिए उपयुक्त लगता है।

बस कोड को देखकर, मांग धारक मुहावरे पर प्रारंभिक क्लीनर और अधिक कुशल लगता है (लेकिन हे, मैं यहां अनुमान लगा रहा हूं)। फिर भी, मुझे अपने सिंगलेट्स में से प्रत्येक में पैटर्न लेना और पैटर्न रखना होगा। कम से कम मेरे लिए, यह समझना मुश्किल होगा कि इस जगह कोड को इस तरह क्यों लिखा गया था ...

मेरा प्रश्न यहां है: कौन सा दृष्टिकोण बेहतर है? और क्यों? यदि आपका उत्तर कोई नहीं है। जावा एसई पर्यावरण में आप इस आवश्यकता से कैसे निपटेंगे?

वैकल्पिक

मैं भव्य मेरी पूरी परियोजना पर फायदा नहीं है बिना इस के लिए CDI का उपयोग कर सकते हैं? वहाँ कोई लेख है?

उत्तर

7

एक और, शायद क्लीनर, विकल्प जोड़ने के लिए।

What is the best approach for using an Enum as a singleton in Java?

+0

अच्छा। लेकिन मुझे यकीन नहीं है कि मैंने यह समझ लिया कि यह कैसे काम करता है। आइए मान लें कि 'Elvis.getAge()' को कुछ सुंदर गहन संचालन की आवश्यकता है, जिन्हें मैं जितना संभव हो सके देरी करना चाहता हूं और केवल एक बार निष्पादित करना चाहता हूं। मैं अपना लोडिंग कोड कहां रखूंगा? एनम कन्स्ट्रक्टर में? –

+0

निश्चित रूप से, यह काम करता है। – djg

+0

@djg मेरे लिए काफी अच्छा लगता है। लेकिन क्या गणना को और भी देरी करने का कोई तरीका है। उदाहरण के लिए, कहें कि मैं स्वतंत्र रूप से कई अलग-अलग संसाधन लोड करना चाहता हूं। इस पैटर्न का उपयोग करके मुझे विभिन्न enums लिखना होगा। क्या केवल एक enum के साथ इसे हासिल करने का कोई तरीका है? आइए 'एल्विस' 'INSTANCE1.getAge()' और 'INSTANCE2.getAge()' के साथ कहें। क्या मैं दोनों थ्रेड-सुरक्षित तरीके से स्वतंत्र रूप से लोड कर सकता हूं? –

7

जहाँ तक पठनीयता के रूप में मैं मांग धारक पर प्रारंभ के साथ जाना होगा: मैं enum भिन्नता सुझाव देते हैं। डबल चेक लॉकिंग, मुझे लगता है, एक दिनांकित और बदसूरत कार्यान्वयन है।

तकनीकी रूप से बोलते हुए, डबल चेक लॉकिंग चुनकर आप हमेशा उस क्षेत्र पर अस्थिर पढ़ लेंगे जहां आप मांग धारक मुहावरे पर प्रारंभिक के साथ सामान्य पढ़ सकते हैं।

3

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

यदि प्रदर्शन एक महत्वपूर्ण चिंता नहीं है, तो सिंक्रनाइज़ getInstance() दृष्टिकोण सबसे सरल है।

+0

तो, जहां तक ​​गति जाती है: मांग धारक पर प्रारंभिकरण> डबल-चेक किए गए लॉकिंग> सिंक्रनाइज़ विधि सही है? मैं यही सोचता हूं। शायद यह कुछ बुरा माइक्रो-बेंचमार्किंग के लिए समय है। –

+0

@ एंथनी, यह सही है। मूल रूप से मांग धारक प्राप्त करता है कि आप डीसीएल को अस्थिर भार के बिना क्या करना चाहते हैं। –

+0

@ एंथनी - माइक्रो बेंचमार्किंग बुरा नहीं है। परिणाम प्राप्त करना मुश्किल है जो सार्थक हैं, और आपके असली उपयोग-मामले पर लागू होते हैं। –

7

प्रारंभिक ऑन-डिमांड धारक केवल एक सिंगलटन के लिए काम करता है, आपके पास प्रति-उदाहरण आलसी लोड तत्व नहीं हो सकते हैं। डबल-चेक लॉकिंग उन सभी लोगों पर एक संज्ञानात्मक बोझ लगाती है जिन्हें कक्षा को देखना है, क्योंकि सूक्ष्म तरीकों से गलत होना आसान है। हम जब तक हम our concurrency library

में उपयोगिता वर्ग में पैटर्न समझाया इस के साथ परेशानी के सभी प्रकार किया करते थे हम निम्नलिखित विकल्प हैं:

Supplier<ExpensiveThing> t1 = new LazyReference<ExpensiveThing>() { 
    protected ExpensiveThing create() { 
    … // expensive initialisation 
    } 
}; 

Supplier<ExpensiveThing> t2 = Lazy.supplier(new Supplier<ExpensiveThing>() { 
    public ExpensiveThing get() { 
    … // expensive initialisation 
    } 
}); 

दोनों जहाँ तक उपयोग का सवाल है समान अर्थ विज्ञान है। दूसरा फॉर्म प्रारंभिकरण के बाद जीसी के लिए उपलब्ध आंतरिक आपूर्तिकर्ता द्वारा उपयोग किए जाने वाले किसी भी संदर्भ को बनाता है। दूसरे फॉर्म में टीटीएल/टीटीआई रणनीतियों के साथ टाइमआउट के लिए भी समर्थन है।

+0

कभी-कभी वर्चुअल प्रॉक्सी पैटर्न कहा जाता है ... कार्यान्वयन अच्छी तरह से "थंडरिंग हर्ड" समस्या का समाधान दिखाता है जहां एकाधिक कॉलर एक ही संसाधन का अनुरोध करते हैं लेकिन आप केवल एक बार संसाधन प्राप्त करना चाहते हैं। –

+0

धन्यवाद एलेक्स, हम इसका बहुत उपयोग करते हैं, अच्छी तरह से काम करता है। –

4

प्रारंभ-ऑन-डिमांड धारक सिंगलटन पैटर्न को लागू करने के लिए हमेशा सर्वोत्तम अभ्यास है। यह JVM की निम्न विशेषताओं का बहुत अच्छा उपयोग करता है।

  1. स्टेटिक नेस्टेड कक्षाएं केवल तभी लोड की जाती हैं जब नाम से बुलाया जाता है।
  2. कक्षा लोडिंग तंत्र डिफ़ॉल्ट रूप से संरक्षित है। तो जब एक धागा एक कक्षा शुरू करता है, तो अन्य धागे इसके पूरा होने की प्रतीक्षा करते हैं।

इसके अलावा, आपको सिंक्रनाइज़ कीवर्ड का उपयोग करने की आवश्यकता नहीं है, यह आपके प्रोग्राम को 100 गुना धीमा कर देता है।

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