오로지 한 개의 인스턴트만 제공하는 클래스
public class Singleton1 { /* 외부에서 이 맴버변수로 직접 접근하여 사용할 수 있도록 public static final 로 사용하기도 한다. */ private static Singleton1 singleton1 = new Singleton1(); // 맴버변수로 자기 자신의 클래스의 인스턴스를 가진다. private Singleton1(){ // private 생성자를 사용하여 외부에서 인스턴스를 생성하지 못하게 한다. (현재 클래스에서만 인스턴스 생성 가능) } public static Singleton1 getInstance(){ // getInstance() 메소드를 통해 객체를 static하게 가져온다. return singleton1; }
public class Singleton2 { private static Singleton2 singleton2; private Singleton2(){ } /* synchronized : 현재 데이터를 사용하고 있는 해당 스레드를 제외한 다른 스레드들은 접근할 수 없게 막음 => 데이터의 thread-safe */ public static synchronized Singleton2 getInstance(){ if(singleton2 == null){ singleton2 = new Singleton2(); } return singleton2; }
public class Singleton3 { /** volatile : 변수를 Main Memory에 저장한다는 뜻 => 변수 값 불일치 해결 (변수의 원자성 보장) Java 1.5 * 일반 변수는 멀티쓰레드 환경에서 성능 향상을 위해 Main Memory에서 읽은 변수를 CPU Cache에 저장하게 되는데, 이런 경우 다중 쓰레드가 값을 읽어올 때 변수 값 불일치 문제가 발생할 수 있다. * CPU Cache 보다 Main Memory 비용이 더 크기 때문에 성능에 영향을 미치긴 한다. * 하나의 쓰레드가 Write 하고 나머지 쓰레드는 Read를 하는 경우에만 적합하다 * 여러 쓰레드가 Write 하는 상황에서는 synchronized 변수를 사용 */ private volatile static Singleton3 singleton3; private Singleton3(){} public static Singleton3 getInstance(){ if (singleton3 == null){ // 인스턴스가 생성 된 이후라면 synchronize 까지 아예 가지 않음 => 성능 저하 문제 해결 synchronized (Singleton3.class){ // 동기화 블록 if (singleton3 == null){ singleton3 = new Singleton3(); // 처음으로 진입한 쓰레드만 인스턴스를 생성 } } } return singleton3; } }
public class Singleton4 { private Singleton4(){} private static class SingletonHolder{ static final Singleton4 singleton4 = new Singleton4(); } public static Singleton4 getInstance(){ return SingletonHolder.singleton4; } }
참고 블로그 : https://gregorio78.tistory.com/122