-
0. 들어가며이번 아이템은 싱글턴 패턴을 안정적으로 구현하기 위한 방법들에 대한 내용입니다. 1. 싱글턴이란?
'오직 하나만 생성할 수 있다' 라는 말은 '인스턴스가 하나만 존재해야 한다' 라고 해석할 수도 있습니다. 1.1 싱글턴의 특징1. 메모리 절약모든 객체는 생성되면 JVM 의 heap 메모리에 저장됩니다. 2. 데이터 공유싱글톤으로 구현된 객체는 JVM heap 에 저장된 하나의 객체를 모든 클라이언트들이 공유하게 되는데요. 3. 멀티스레드 환경을 고려해야 함다수의 클라이언트에서 하나의 객체, 즉 하나의 자원을 공유하는 상황이다 보니 자칫하면 치명적인 문제가 발생할 수 있습니다. 4. 싱글턴을 사용하는 클라이언트를 테스트하기 어려움테스트 케이스들을 작성할 때 필연적으로 다양한 입력값, 출력값을 정의해야 합니다. 이런 부분을 방지하고자 한다면 싱글톤 클래스가 특정 인터페이스를 상속하게 하는 방법이 있습니다. interface Something {
void doSomething();
}
class SingletonSomething implements Something {
@Override
public void doSomething() {
// do something
}
} 2. 싱글턴을 구현하는 방법
1,2,3번 방식은 Effective java 에서 제안하는 방식이고, 4번은 추가로 소개하고싶은 방법입니다. 2.1 public static final 필드/**
* 1. public static final 필드 방식
*/
public class Singleton1 {
public static final Singleton1 instance = new Singleton1();
private Singleton1() { }
}
2.2 정적 팩터리 방식정적 팩터리 방식에서는 여러가지 방법을 사용할 수 있습니다.
1) static final 필드 활용/**
* 2. 정적 팩터리 방식
* 1) static final 필드 활용
*/
public class Singleton2_1 {
private static final Singleton2_1 instance = new Singleton2_1();
private Singleton2_1() { }
public static Singleton2_1 getInstance() {
return instance;
}
} 2.1 과 특징이 같습니다.
2) Lazy Initialization(지연 초기화)/**
* 2. 정적 팩터리 방식
* 2) Lazy Initialization(지연 초기화)
*/
public class Singleton2_2 {
private static Singleton2_2 instance;
private Singleton2_2() { }
public static Singleton2_2 getInstance() {
if (instance == null) {
instance = new Singleton2_2();
}
return instance;
}
} 1)번 방법은 사용하지 않아도 불필요하게 객체가 생성된다는 단점이 있었습니다.
3) Lazy Initialization + Synchronization(지연 초기화 + 동기화)/**
* 2. 정적 팩터리 방식
* 3) Lazy Initialization + Synchronization(지연 초기화 + 동기화)
*/
public class Singleton2_3 {
private static Singleton2_3 instance;
private Singleton2_3() { }
public static synchronized Singleton2_3 getInstance() {
if (instance == null) {
instance = new Singleton2_3();
}
return instance;
}
} 멀티스레드 환경에서 레이스 컨디션이 발생하는 경우를 방지하기 위해 동기화를 사용하는 방법입니다.
4) LazyHolder 방식/**
* 4. LazyHolder 방식
*/
public class Singleton4 {
private Singleton4() { }
private static class LazyHolder {
private static final Singleton4 INSTANCE = new Singleton4();
}
public static Singleton4 getInstance() {
return LazyHolder.INSTANCE;
}
} LazyHolder 방식은 지연 초기화 방식의 성능적 문제를 개선하기 위해 제안된 방법입니다.
3. 조금 더 생각해볼 것들
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
오,, 이 방식은 처음 보는데,, 이런 방식도 있군요,, 😵 |
Beta Was this translation helpful? Give feedback.
-
싱글턴을 만들때 3) Lazy Initialization + Synchronization(지연 초기화 + 동기화) 방식으로 멀티스레딩의 문제를 해결하기 위해 사용한 synchronized로 인한 성능의 문제를 해결하는 방법으로
public class Singleton3 {
private volatile static Singleton3 uniqueInstance;
private Singleton3() {}
public static Singleton3 getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton3.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton3();
}
}
}
return uniqueInstance;
}
}
이번 아이템을 통해 싱글턴을 만드는 여러 방법에 대해 알게 되었고 싱글턴을 만들게 됨으로써 생기는 문제점을 해결하기 위해 각 방식이 생겨나게 된 이유도 알게 되었습니다. 정리 감사합니다. |
Beta Was this translation helpful? Give feedback.
-
정리 해주신 글 잘 읽었습니다 👍 public class Singleton { // Lazy loading with a holder
private static class SingletonHolder {
static {
System.out.println("In SingletonHolder static block.");
}
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
System.out.println("In getInstance().");
return SingletonHolder.INSTANCE;
}
private Singleton() {
System.out.println("In constructor.");
}
private void doSomething() {
System.out.println("Singleton working.");
}
public static void main(String[] args) {
System.out.println("Start of main.");
Singleton.getInstance().doSomething();
System.out.println("End of main.");
}
}
public class Singleton { // Eager loading without a holder
static {
System.out.println("In Singleton static block.");
}
private static final Singleton INSTANCE = new Singleton();
public static Singleton getInstance() {
System.out.println("In getInstance().");
return INSTANCE;
}
private Singleton() {
System.out.println("In constructor.");
}
private void doSomething() {
System.out.println("Singleton working.");
}
public static void main(String[] args) {
System.out.println("Start of main.");
Singleton.getInstance().doSomething();
System.out.println("End of main.");
}
}
|
Beta Was this translation helpful? Give feedback.
싱글턴을 만들때 3) Lazy Initialization + Synchronization(지연 초기화 + 동기화) 방식으로 멀티스레딩의 문제를 해결하기 위해 사용한 synchronized로 인한 성능의 문제를 해결하는 방법으로
4)
LazyHolder 방식을 사용 하였는데 저도 처음 알게 되었습니다.3)
문제를 해결하는 방법으로4)
말고도 알고있는 내용으로는DCL(Double Checked Locking) 방식에 대해 알고 있습니다.
3)
방식의 문제는 동기화가 꼭 필요한 시점은 …