Singleton (2)
154293 단어 Singleton
만약 프로그램이 처음부터 어떤 단례를 필요로 하고 이 단례를 만드는 것이 그리 힘들지 않을 때 우리는 이런 방식을 고려할 수 있다.
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
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Java]기본6~15강 까지의 내용 정리클래스 메소드 사용 방법 메소드 실행 순서 over(넘치다)+load(저장하다)로, 메소드의 이름이 같으면서 매개변수의 자료형,갯수, 순서 중 하나 이상이 다른 경우 동일한 메소드 명으로 실행 가능 생성자 클래스 명...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.