싱글톤 패턴 (Singleton Pattern)은 디자인 패턴 중에 하나로, 클래스의 객체를 한 개만 생성해서 그 객체만을 사용하는 패턴이다.
상태값이 없고 기능만을 수행하는 클래스를 사용하려고 여러 곳에서 객체를 생성하면 메모리가 낭비된다. 이런 경우 싱글톤 패턴을 통해 객체를 한 개만 생성하고 이를 돌려쓴다면 메모리적으로 효율이 좋아진다. 자원 낭비 또한 방지할 수 있다.
사용 예시
상태가 없는(Stateless) 클래스, 로깅, 설정 관리, DB 연결 풀

기존 클래스처럼 생성자로 객체를 만드는 것이 아니라 static 메서드인 getInstance()로 객체를 만든다.
멀티쓰레드 환경에서 우리가 의도한 것고는 다르게 객체가 여러개 생길 수 이싸.
EX) 두 개의 쓰레드가 각자 싱글턴 패턴을 이용한 클래스를 사용하려고 getInstance() 메서드를 호출했다고 가정
1번 쓰레드가 null 확인을 위해 캐시를 확인한다. 확인 후에 객체를 만들려고 시도하려고 한다.
↓
1번이 객체를 다 만들기 전에 2번 쓰레드가 작업을 시작한다. 캐시를 봤는데 Null임을 확인한 2번 쓰레드는 If문 내부를 실행해서 객체를 생성 및 반환한다.
↓
2번 쓰레드의 시간이 끝나고 1번 쓰레드가 작업대에서 못했던 객체 생성 및 반환을 짆ㅇ한다.
↓
싱글톤 패턴에서 의도치 않게 객체가 두 개가 생겨버렸다!!
↓
동시성 문제 발생!!!

클래스 멤버에 직접 객체를 초기화 해버리는 방법
클래스 로더(Class loader)가 클래스를 로딩할 때 객체를 생성해주게 된다

객체 초기화를 직접적으로 하는 것이 아니라 static 블록에 넣는 것
(Static 블록 = 클래스가 최초 로딩되는 1회에만 수행이 되는 블록)
Exception에 대한 처리로직을 구현할 수 있게되어 처리가 가능해짐

달라진 점은 getInstance() 메서드에 synchronized라는 키워드가 붙은 것

Synchronized의 무분별한 사용을 막기 위해 if문이라는 관문을 하나 설치하는 것이다.
이렇게 되면 synchronized의 사용이 줄어들게 되어서 성능 저하를 억제할 수 있게 된다.

Synchronized의 무분별한 사용을 막기 위해 if문이라는 관문을 하나 설치하는 것이다.
이렇게 되면 synchronized의 사용이 줄어들게 되어서 성능 저하를 억제할 수 있게 된다.

Inner class 특징을 활용한 방식
LazyHolder 클래스는 Inner Class라 Singleton클래스가 클래스로더에 의해 로딩이 될 때는 로딩되지 않음
getInstance() 메서드를 호출할 때 로딩이 되고 객체가 생성되게 됨.
멀티쓰레드 환경에서도 안전하고, 사용될 때만 객체가 생성되니 메모리 낭비도 없다

Enum 인스턴스는 기본적으로 멀티쓰레드 환경에서 나올 수 있는 문제를 해결해준다.
Enum의 특성을 이용한 방식