Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/singleton/SingletonPattern.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package singleton;

public class SingletonPattern {
public static void main(String[] args) {

}
}
48 changes: 48 additions & 0 deletions src/singleton/boiler/ChocolateBoilerEnum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package singleton.boiler;

/**
* enum으로 싱글톤을 생성하면
* 동기화 문제, 클래스 로딩 문제, 리플렉션, 직렬화, 역직렬화 문제를 해결할 수 있다.
*/
public enum ChocolateBoilerEnum {
UNIQUE_INSTANCE;

private boolean empty;
private boolean boiled;

Comment on lines +3 to +12
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 현재 가장 완벽한 enum 클래스를 활용한 싱글톤 방식

동기화 문제, 클래스 로딩 문제, 리플렉션, 직렬화, 역직렬화 문제를 해결할 수 있다.

/**
* 보일러가 비어있을 경우에만 재료를 넣는다
*/
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}

/**
* 보일러가 가득차있고, 다 끓여진 상태에서만 초콜릿을 흘려보낸다
*/
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}

/**
* 보일러가 가득차있고, 아직 끓지않은 상태에서만 끓인다
*/
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}

public boolean isEmpty() {
return empty;
}

public boolean isBoiled() {
return boiled;
}
}
56 changes: 56 additions & 0 deletions src/singleton/boiler/ChocolateBoilerFinal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package singleton.boiler;

/**
* public static final field
*/
public class ChocolateBoilerFinal {
private boolean empty;
private boolean boiled;

// 싱글톤 인스턴스를 처음부터 초기화한다.
private static final ChocolateBoilerFinal uniqueInstance = new ChocolateBoilerFinal();

private ChocolateBoilerFinal() {
empty = true;
boiled = false; // 보일러가 비어있을 때만 돌아간다
}

public static ChocolateBoilerFinal getInstance() {
return uniqueInstance;
}

Comment on lines +3 to +21
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 게으른 인스턴스 생성 방식대신, 처음부터 싱글톤 패턴을 초기화하는 방식

/**
* 보일러가 비어있을 경우에만 재료를 넣는다
*/
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}

/**
* 보일러가 가득차있고, 다 끓여진 상태에서만 초콜릿을 흘려보낸다
*/
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}

/**
* 보일러가 가득차있고, 아직 끓지않은 상태에서만 끓인다
*/
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public boolean isEmpty() {
return empty;
}

public boolean isBoiled() {
return boiled;
}
}
59 changes: 59 additions & 0 deletions src/singleton/boiler/ChocolateBoilerLazy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package singleton.boiler;

/**
* lazy initialization -> 동기화 문제
*/
public class ChocolateBoilerLazy {
private boolean empty;
private boolean boiled;

private static ChocolateBoilerLazy uniqueInstance;

private ChocolateBoilerLazy() {
empty = true;
boiled = false; // 보일러가 비어있을 때만 돌아간다
}

public static ChocolateBoilerLazy getInstance() {
if (uniqueInstance == null) { // 멀티 스레딩 환경에서 최초로 인스턴스가 생성될 시점에 동기화 문제 발생
uniqueInstance = new ChocolateBoilerLazy();
}

return uniqueInstance;
}
Comment on lines +3 to +23
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 멀티 스레드 환경에서 동기화 문제가 있는 고전적 방식의 싱글톤 패턴


/**
* 보일러가 비어있을 경우에만 재료를 넣는다
*/
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}

/**
* 보일러가 가득차있고, 다 끓여진 상태에서만 초콜릿을 흘려보낸다
*/
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}

/**
* 보일러가 가득차있고, 아직 끓지않은 상태에서만 끓인다
*/
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public boolean isEmpty() {
return empty;
}

public boolean isBoiled() {
return boiled;
}
}
61 changes: 61 additions & 0 deletions src/singleton/boiler/ChocolateBoilerSynchronized.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package singleton.boiler;

/**
* lazy initialization & synchronized
*/
public class ChocolateBoilerSynchronized {
private boolean empty;
private boolean boiled;

private static ChocolateBoilerSynchronized uniqueInstance;

private ChocolateBoilerSynchronized() {
empty = true;
boiled = false; // 보일러가 비어있을 때만 돌아간다
}

// 인스턴스가 최초로 초기화 되는 시점에만 동기화가 필요하지만,
// 이 방식은 항상 동기화가 일어나 속도 문제가 있다.
public static synchronized ChocolateBoilerSynchronized getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new ChocolateBoilerSynchronized();
}

return uniqueInstance;
}
Comment on lines +3 to +25
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. synchronized 키워드를 활용하여 동기화 문제를 해결한 방식

하지만 속도 문제가 존재한다.


/**
* 보일러가 비어있을 경우에만 재료를 넣는다
*/
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}

/**
* 보일러가 가득차있고, 다 끓여진 상태에서만 초콜릿을 흘려보낸다
*/
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}

/**
* 보일러가 가득차있고, 아직 끓지않은 상태에서만 끓인다
*/
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public boolean isEmpty() {
return empty;
}

public boolean isBoiled() {
return boiled;
}
}
65 changes: 65 additions & 0 deletions src/singleton/boiler/ChocolateBoilerVolatile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package singleton.boiler;

/**
* lazy initialization & volatile
*/
public class ChocolateBoilerVolatile {
private boolean empty;
private boolean boiled;

private volatile static ChocolateBoilerVolatile uniqueInstance;

private ChocolateBoilerVolatile() {
empty = true;
boiled = false; // 보일러가 비어있을 때만 돌아간다
}

public static ChocolateBoilerVolatile getInstance() {
if (uniqueInstance == null) {
// 인스턴스가 최초로 초기화되는 시점에만 동기화가 일어난다.
// 다만 java 5 버전 이하의 JVM에서는 volatile 키워드가 제대로 동작하지 않는 이슈가 있다.
synchronized (ChocolateBoilerVolatile.class) {
if (uniqueInstance == null) {
uniqueInstance = new ChocolateBoilerVolatile();
}
}
}

return uniqueInstance;
}

Comment on lines +2 to +30
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. synchroized 방식의 속도 문제를 해결하기 위해 volatile 키워드를 활용

다만 java5 버전 이하에서는 volatile 키워드가 제대로 동작하지 않는 이슈가 있다

/**
* 보일러가 비어있을 경우에만 재료를 넣는다
*/
public void fill() {
if (isEmpty()) {
empty = false;
boiled = false;
}
}

/**
* 보일러가 가득차있고, 다 끓여진 상태에서만 초콜릿을 흘려보낸다
*/
public void drain() {
if (!isEmpty() && isBoiled()) {
empty = true;
}
}

/**
* 보일러가 가득차있고, 아직 끓지않은 상태에서만 끓인다
*/
public void boil() {
if (!isEmpty() && !isBoiled()) {
boiled = true;
}
}
public boolean isEmpty() {
return empty;
}

public boolean isBoiled() {
return boiled;
}
}
Loading