हाँ, यह आवश्यक है। कई तरीके हैं जिनसे आप आलसी इनिशियलाइज़ेशन के साथ थ्रेड सेफ्टी हासिल कर सकते हैं:
ड्रेकोनियन तुल्यकालन:
private static YourObject instance;
public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}
इस समाधान के लिए आवश्यक है कि हर धागे को तब सिंक्रनाइज़ किया जाए जब वास्तव में केवल पहले कुछ की आवश्यकता हो।
दोहरा चेक सिंक्रनाइज़ेशन :
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance;
if (r == null) {
synchronized (lock) { // While we were waiting for the lock, another
r = instance; // thread may have instantiated the object.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
यह समाधान सुनिश्चित करता है कि केवल पहले कुछ धागे जो आपके सिंगलटन का अधिग्रहण करने का प्रयास करते हैं, उन्हें लॉक प्राप्त करने की प्रक्रिया से गुजरना होगा।
मांग पर आरंभ :
private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}
public static YourObject getInstance() {
return InstanceHolder.instance;
}
यह समाधान थ्रेड सुरक्षा सुनिश्चित करने के लिए वर्ग स्मृति के बारे में जावा मेमोरी मॉडल की गारंटी का लाभ उठाता है। प्रत्येक वर्ग को केवल एक बार लोड किया जा सकता है, और इसे केवल तब लोड किया जाएगा जब इसकी आवश्यकता होगी। इसका मतलब है कि पहली बार getInstance
बुलाया गया है, InstanceHolder
लोड किया instance
जाएगा और बनाया जाएगा, और चूंकि यह ClassLoader
एस द्वारा नियंत्रित किया जाता है , इसलिए कोई अतिरिक्त सिंक्रनाइज़ेशन आवश्यक नहीं है।