1. 싱글톤 의미
클래스가 하나의 인스턴스만 가질 수 있게 보증한다.
2. 써야할 때
어떤 클래스의 인스턴스 생성 개수의 제어가 필요할 때
3. 사용 예
원도우 매니저
프린터 스풀러
4. 싱글톤 코드1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | package com.tistory.janggom.base; class Singleton{ private static Singleton one; protected Singleton(){} public static Singleton getInstance(){ if(one == null){ synchronized(Singleton.class){ if(one == null){ //Double Checked Locking one = new Singleton(); } } } return one; } } class SingletonEx { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1); System.out.println(s2); } } | cs |
보통 책에 나오는 기본적인 thread-safe한 싱글톤
생성자를 private를 해서 외부에서의 new 키워드를 막고,
다른 스레드를 막기 위해 더블 체크 사이에 synchronized를 사용했다.
구글링해서 발견한건데 이 코드가 완벽한것처럼 보이는데
초반에 메모리 할당 시간이랑 인스턴스 생성 시간 차이로 인해 다음 스레드가 null값을 리턴할 경우가 있단다!!!!
정말로 극극극극극극극악의 확률이라서 걍 써도 무방할 듯 하다.
걱정되면 인스턴스 생성후(16) thread.sleep를 아주 조금 주는 방법이 있겠다.
4. 싱글톤 코드2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package com.tistory.janggom.threadsafe; class Singleton { private Singleton() {} public static Singleton getInstance() { return LazyHolder.INSTANCE; } private static class LazyHolder { // 내부 클래스(참조시에만 메모리에 로딩, Lazy Initialization) private static final Singleton INSTANCE = new Singleton(); } } class SingletonEx2 { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1); System.out.println(s2); } } | cs |
동기화(synchronized)를 사용 안해도 되는 싱글톤
내부 클래스를 사용해서 safe도 보증한다.