Singleton (2)

154293 단어 Singleton
0)Eager initialization
만약 프로그램이 처음부터 어떤 단례를 필요로 하고 이 단례를 만드는 것이 그리 힘들지 않을 때 우리는 이런 방식을 고려할 수 있다.
1
2
3
4
5
6
7
8
9
public class Singleton {  private static final Singleton INSTANCE = new Singleton();   private Singleton() {}   public static Singleton getInstance() {  return INSTANCE;  } } 

이러한 실현 방식은 몇 가지 특징이 있다.
인스턴스가 생성됩니다(Eager initialization). getInstance() 방법은 다선정 동기화 문제를 해결하기 위해 synchronize를 추가할 필요가 없다. final 키는 실례가 변할 수 없고 하나만 존재할 수 있음을 확보했다.
1)Lazy initialization
불러오기를 게을리 하는 방식은 첫 번째 사용이 되었을 때 비로소 하나의 예가 만들어집니다.먼저 위험이 있는 묘사법을 보아라.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public final class LazySingleton {  private static volatile LazySingleton instance = null;   // private constructor  private LazySingleton() {  }   public static LazySingleton getInstance() {  if (instance == null) {  synchronized (LazySingleton.class) {  instance = new LazySingleton();  }  }  return instance;  } } 

주의: 위의 글쓰기는 사실 라인이 안전하지 않습니다. 두 개의 Thread가 getInstance 방법에 동시에 들어갔다고 가정하면 instance==null를 판단한 다음에synchronized 때문에 하나씩 실행됩니다. 이렇게 하면 두 개의 실례를 얻을 수 있습니다.이 문제를 해결하려면 다음과 같은 전형적인 더블-check 방식이 필요하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LazySingleton {  private static volatile LazySingleton instance = null;   private LazySingleton() {  }   public static LazySingleton getInstance() {  if (instance == null) {  synchronized (LazySingleton .class) {  if (instance == null) {  instance = new LazySingleton ();  }  }  }  return instance;  } } 

또 다른 간략하고 직관적인 대체 문법은 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class LazySingleton {  private static volatile LazySingleton instance = null;   private LazySingleton() {  }   public static synchronized LazySingleton getInstance() {  if (instance == null) {  instance = new LazySingleton ();  }  return instance;  } } 

2)Static block initialization
프로그램의 마운트 순서에 대해 조금 알고 있다면 Static Block의 초기화는 마운트 클래스가 실행된 후에 Constructor가 실행되기 전에 실행된다는 것을 알 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class StaticBlockSingleton {  private static final StaticBlockSingleton INSTANCE;   static {  try {  INSTANCE = new StaticBlockSingleton();  } catch (Exception e) {  throw new RuntimeException("Error, You Know This, Haha!", e);  }  }   public static StaticBlockSingleton getInstance() {  return INSTANCE;  }   private StaticBlockSingleton() {  // ...  } } 

위의 글쓰기에는 폐단이 하나 있다. 만약에 우리 클래스에 몇 개의static 변수가 있다면 프로그램의 초기화는 그 중 1, 2개만 있으면 우리는 여분의 static initialization을 할 것이다.
3)Bill Pugh solution
University of Maryland Computer Science researcher Bill Pugh는 기사initialization on demand holder idiom를 쓴 적이 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Singleton {  // Private constructor prevents instantiation from other classes  private Singleton() { }   /**  * SingletonHolder is loaded on the first execution of Singleton.getInstance()   * or the first access to SingletonHolder.INSTANCE, not before.  */  private static class SingletonHolder {  public static final Singleton INSTANCE = new Singleton();  }   public static Singleton getInstance() {  return SingletonHolder.INSTANCE;  } } 

Singleton Holder 클래스는 필요할 때 초기화되며, Singleton 클래스의 다른 static 구성원 변수의 사용에 영향을 주지 않습니다.이 방법은 라인이 안전하고volatile과synchronized를 사용하지 않습니다.
4)Using Enum
이것은 가장 간편하고 안전한 방법이다.뚜렷한 결점이 없고 다음에 이야기할 서열화의 위험을 피했다.
1
2
3
4
5
6
public enum Singleton {  INSTANCE;  public void execute (String arg) {  // perform operation here   } } 

Serialize and de-serialize
어떤 경우 서열화가 필요할 때 일반적인 단일 모드는readResolve 방법을 추가해야 합니다. 그렇지 않으면 이상이 발생할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class DemoSingleton implements Serializable {  private volatile static DemoSingleton instance = null;   public static DemoSingleton getInstance() {  if (instance == null) {  instance = new DemoSingleton();  }  return instance;  }   protected Object readResolve() {  return instance;  }   private int i = 10;   public int getI() {  return i;  }   public void setI(int i) {  this.i = i;  } } 

위의 것만 가지고는 부족합니다. 우리는serialVersionUID를 추가해야 합니다. 예를 들어 아래의 총결을 보십시오.
Conclusion
다음 두 가지 방법 중 하나를 사용하면 성능이 향상되고 시리얼화된 문제가 없는 완벽한 기능을 구현할 수 있습니다.
Bill Pugh(Inner Holder)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DemoSingleton implements Serializable {  private static final long serialVersionUID = 1L;   private DemoSingleton() {  // private constructor  }   private static class DemoSingletonHolder {  public static final DemoSingleton INSTANCE = new DemoSingleton();  }   public static DemoSingleton getInstance() {  return DemoSingletonHolder.INSTANCE;  }   protected Object readResolve() {  return getInstance();  } } 

Enum
1
2
3
4
5
6
public enum Singleton {  INSTANCE;  public void execute (String arg) {  // perform operation here   } } 

참고 자료
Singleton Pattern
Singleton Pattern In Java
전재자: http://kesenhoo.github.com

좋은 웹페이지 즐겨찾기