← Back to Advanced Java Course | Chapter 6: Design Patterns | Lesson 2 of 14

Java का Singleton Pattern

Singleton pattern यह सुनिश्चित करता है कि पूरे program में किसी चीज़ की सिर्फ एक copy हो, जैसे किसी school में एक principal। सब वही एक share करते हैं।
Syntax
java
class Singleton {
    private static Singleton instance;
    private Singleton() { }
    public static Singleton getInstance() {
        if (instance == null) instance = new Singleton();
        return instance;
    }
}

Eager Initialization

Eager initialization Singleton का एकमात्र instance उसी क्षण बना देता है जब class JVM द्वारा load होती है, चाहे यह आखिर में उपयोग हो या न हो। implement करने का यह सबसे सरल तरीका है, लेकिन इसकी कमी यह है कि यह उस run में भी instantiation की लागत हमेशा चुकाता है जहां singleton की असल में कभी ज़रूरत नहीं पड़ती।

उदाहरण: Eager Initialization

java
public class Main {
	static class Singleton {
		static final Singleton INSTANCE = new Singleton(); // created at class-load time, whether used or not
		private Singleton() {}
	}
	public static void main(String[] args) {
		System.out.println(Singleton.INSTANCE == Singleton.INSTANCE);
	}
}

Lazy Initialization

Lazy initialization इसके बजाय instance बनाने को तब तक टाल देता है जब तक यह पहली बार वाकई request नहीं होता, आगे का अनावश्यक काम टालते हुए। concurrent access के तहत lazy initialization को सुरक्षित बनाने के लिए, creation logic को एक synchronized method या block में wrap करना होगा ताकि दो threads दोनों अलग instances न बना सकें।

उदाहरण: Lazy Initialization

java
public class Main {
	static class Singleton {
		private static Singleton instance;
		private Singleton() {}
		static synchronized Singleton getInstance() {
			if (instance == null) instance = new Singleton(); // created only when first requested
			return instance;
		}
	}
	public static void main(String[] args) {
		System.out.println(Singleton.getInstance() == Singleton.getInstance());
	}
}

Double-Checked Locking

Double-checked locking हर access पर synchronize करने का overhead घटाता है यह दो बार जांच कर कि instance पहले से मौजूद है या नहीं: एक बार lock पाने से पहले, और फिर एक बार lock पाने के बाद, instance को सिर्फ तभी बनाते हुए जब यह अभी भी दोनों बार गायब हो। इस pattern के सुरक्षित होने के लिए instance field को volatile declare होना चाहिए, क्योंकि इसके बिना, दूसरे threads एक आधा-बना object देख सकते हैं।

उदाहरण: Double-Checked Locking

java
// Define the class Main
public class Main {
	// Define the class Singleton
	static class Singleton {
		private static volatile Singleton instance;
		private Singleton() {}
		static Singleton getInstance() {
			// Check whether instance == null
			if (instance == null) {
				// synchronized lets only one thread run this code at a time
				synchronized (Singleton.class) {
					if (instance == null) instance = new Singleton();
				}
			}
			// Send instance back to the caller
			return instance;
		}
	}
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Print a line to the console
		System.out.println(Singleton.getInstance() == Singleton.getInstance());
	}
}

Enum Singleton

Enum singletons को JVM enums को handle करने के तरीके में बनी गारंटियों के कारण thread safety और serialization के ज़रिए duplicate instantiation से सुरक्षा लगभग मुफ़्त में मिल जाती है। कई अनुभवी Java developers इसे practice में Singleton implement करने का सबसे सरल और मज़बूत तरीका मानते हैं।

उदाहरण: Enum Singleton

java
public class Main {
	enum Singleton {
		INSTANCE;
		void doWork() { System.out.println("Working"); }
	}
	public static void main(String[] args) {
		Singleton.INSTANCE.doWork(); // thread-safe and serialization-safe for free
	}
}

Serialization & Reflection Protection

एक conventional (non-enum) Singleton गलती से deserialization के दौरान, या यहां तक कि reflection से किसी private constructor को दूसरी बार forcibly call करके भी duplicate हो सकता है। readResolve() method implement करना आपको deserialization को intercept करने और एक नए instance के बजाय मौजूदा singleton instance return करने देता है।

उदाहरण: Serialization & Reflection Protection

java
import java.io.*;
public class Main {
	static class Singleton implements Serializable {
		static final Singleton INSTANCE = new Singleton();
		private Singleton() {}
		protected Object readResolve() {
			return INSTANCE; // returns the existing instance instead of a new one during deserialization
		}
	}
	public static void main(String[] args) {
		System.out.println(Singleton.INSTANCE);
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. multi-threaded code में if (instance == null) instance = new Singleton(); के साथ lazy initialization का उपयोग करना, जो दो instances बना सकता है।
  2. field को volatile चिह्नित किए बिना double-checked locking का उपयोग करना, जो किसी दूसरे thread को आधा-बना object देखने दे सकता है।
  3. constructor को public छोड़ देना, ताकि कोई भी code new Singleton() call कर सके और pattern टूट जाए।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.