2015-11-12 9 views
7

जब जावा में एक स्थिर सिंगलटन आप यह कर सकते हैं के आलसी प्रारंभ कर:क्या हम जावा सदस्य की दर्द रहित आलसी लोडिंग को उसी तरह से प्राप्त कर सकते हैं जिस तरह से हम स्थिर सिंगलटन के साथ कर सकते हैं?

public class Bob { 

    private static class SingletonWrapper { 
     private static final Bob instance = new Bob(); 
    } 

    public static Bob getInstance() { 
     return SingletonWrapper.instance; 
    } 

} 

क्योंकि भीतरी वर्ग SingletonWrapper केवल लोड किया जाता है जब पहली पहुँचा Bob() तक getInstance() कहा जाता है नहीं बनाई गई है।

मेरा सवाल यह है कि क्या ऐसी कोई भी चाल है जिसका प्रयोग किसी गैर-स्थैतिक संदर्भ में सदस्य चर के आलसी तत्कालता के लिए किया जा सकता है।

public class Bob { 

    // Clearly this doesn't work as not lazy 
    private final InnerWrapper wrapper = new InnerWrapper(); 

    private class InnerWrapper { 
     private final Jane jane = new Jane(); 
    } 

    public Jane getJane() { 
     return wrapper.jane; 
    } 

} 

वहाँ किसी भी तरह से हम Bob भीतर Jane का एक उदाहरण है और पुनः जाँच लें ताला या AtomicReference का उपयोग किए बिना सुरक्षित रूप से थ्रेड है केवल मांग पर बनाया उदाहरण कर सकता है। आदर्श रूप से प्राप्त विधि इन उदाहरणों में से एक के रूप में सरल रहनी चाहिए, लेकिन यदि यह संभव नहीं है तो get विधि का सबसे सरल और तेज़ संभव (सबसे प्रभावी) निष्पादन आदर्श होगा।

+0

@assylias टिप्पणी कहते हैं कि आलसी प्रारंभ नहीं मारूंगा। जैसे ही आप 'बॉब' बनाते हैं, आप हमेशा भी और तुरंत 'जेन' बनाते हैं। –

+0

मेरा बुरा मैंने बहुत तेज़ पढ़ा - किसी भी कारण से आप परमाणु संदर्भ नहीं चाहते हैं? यह संभवतः सीएचएम विकल्प से बेहतर प्रदर्शन करेगा। – assylias

+0

@assylias कोई विशिष्ट कारण नहीं है। असल में मैं सिर्फ यह जानना चाहता हूं कि मेरे विकल्प क्या हैं - इस बात पर विचार करना कि स्थिर रैपर चाल कितनी सरल और प्रभावी है, सिंगलटन की आलसी शुरुआत के लिए यह शर्म की बात है कि हम सदस्यों की आलसी शुरुआत के लिए कुछ नहीं आ सकते हैं, –

उत्तर

8

नहीं, कक्षाओं को प्रारंभ करने के लिए तत्काल प्रकार के लिए कोई सिंक्रनाइज़ेशन नियम नहीं हैं। आपको उन्हें खुद जोड़ना होगा। चाहे आप इसे डबल चेक लॉकिंग के साथ करते हैं या कुछ अन्य तंत्र आपके ऊपर है।

जावा 8 के साथ शुरुआत, मैं आलसीपन प्राप्त करने के लिए ConcurrentHashMap#computeIfAbsent का उपयोग करना चाहता हूं।

class Bob { 
    private final ConcurrentHashMap<String, Jane> instance = new ConcurrentHashMap<>(1); 

    public Jane getJane() { 
     return instance.computeIfAbsent("KEY", k -> new Jane()); // use whatever constant key 
    } 
} 

धागे की सुरक्षा बाधा के बिना आलसी प्रारंभ करने के लिए भी these solutions रहे हैं। मैं एक बहुप्रचारित संदर्भ के लिए उन्हें साफ रूप से अनुकूलित करने में सक्षम नहीं था।

टिप्पणियों में कहा गया है कि, डबल चेक लॉकिंग इन समाधानों से हमेशा तेज रहेगी क्योंकि उनमें कार्यान्वयन को छिपाने के लिए सभी फ्लाफ शामिल नहीं हैं।

+0

जबकि यह साफ कोड है प्रदर्शन प्रदर्शन की तुलना कैसे करता है? –

+0

डबल चेक लॉकिंग शायद सबसे तेज़ होगा क्योंकि कोई अतिरिक्त चेक नहीं है। आप उदाहरण प्राप्त करने के लिए जो कुछ करना चाहते हैं उस पर आप कर रहे हैं। –

+1

गुवा का उपयोग करके मेरे वर्बोज़ समाधान से बेहतर तरीका, भले ही तर्क समान है –

2

आप अमरूद का कैश का उपयोग कर सकते हैं:

public class Bob { 
    private final static Object KEY = new Object(); 

    private final Cache<Object, Jane> cache = 
     CacheBuilder.newBuilder() 
        .build(new CacheLoader<Object, Jane>() { 
           @Override 
           public Jane load() { 
            return new Jane(); 
           } 
          }); 

    public Jane getJane() { 
     return cache.get(KEY); 
    } 

} 
+0

यह कैश का मुख्य उपयोग केस नहीं है: स्वचालित निष्कासन। एक समवर्ती हैश मैप काम करेगा और अमरूद कैश से अच्छा प्रदर्शन करेगा – Zava

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

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