Java에서의 싱글톤패턴

Jinjin·2023년 8월 21일
0
post-thumbnail

싱글톤 패턴?


: 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다.이와 같은 디자인 유형을 싱글톤 패턴이라고 한다.

✔ 주로 공통된 객체를 여러개 생성해서 사용하는 DBCP(DataBase Connection Pool)와 같은 상황에서 많이 사용된다.

싱글톤 패턴은 객체의 인스턴스를 한 개만 생성되게 하는 패턴 이다.

✔ 이러한 패턴은 주로 프로그램 내에서 하나로 공유를 해야하는 객체가 존재할 때 해당 객체를 싱글톤으로 구현해서 모든 사용자 또는 프로그램이 해당 객체를 공유하며 사용하도록 할 때 사용한다.

✔ 싱글톤 패턴을 사용하는 경우
📌 프로그램 내에서 하나의 객체만 존재해야 하는 경우
📌 프로그램 내에서 여러 부분에서 해당 객체를 공유하여 사용해야한다.




싱글톤 패턴을 사용하는 이유?


1. 메모리 측면의 이점

: 한 개의 인스턴스만을 고정 메모리 영역에 생성하고 추후 해당 객체를 접근할 때 메모리 낭비를 방지할 수 있다.

2. 속도 측면의 이점

: 생성된 인스턴스를 사용할 때는 이미 생성된 인스턴스를 활용하여 속도 측면에 이점이 있다.

3. 데이터 공유가 쉽다.

: 전역으로 사용하는 인스턴스이기 때문에 다른 여러 클래스에서 데이터를 공유하며 사용할 수 있다.
하지만 동시성 문제가 발생할 수 있어 유의하여 설계해야 한다.




싱글톤 패턴 구현하기


public class Singleton {
    // 단 1개만 존재해야 하는 객체의 인스턴스로 static 으로 선언
    private static Singleton instance;

    // private 생성자로 외부에서 객체 생성을 막아야 한다.
    private Singleton() {
    }

    // 외부에서는 getInstance() 로 instance 를 반환
    public static Singleton getInstance() {
        // instance 가 null 일 때만 생성
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  • static으로 선언해서 최초에 메모리에 한 번만 만들어진다.
  • private로 생성자를 만들엇 외부에서의 접근을 막는다.



Multi-thread에서의 싱글톤


📌 멀티스레드 환경에서 싱글 톤을 사용했을 때 발생할 수 있는 2가지의 문제점과 해결 방안

1. 여러 개의 인스턴스 생성

  • 멀티스레드 환경에서 인스턴스가 없을 때 동시에 아래의 getInstance() 메소드를 호출해서 각각 새로운 인스턴스를 생성할 수 있다.
<    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

2. 변수 값의 일관성 실패

  • 여러 개의 스레드에서 plusCount()를 동시에 실행하면 일관되지 않은 값들이 생길 수 있다.
public class Singleton {
    private static Singleton instance;
    private static int count = 0;
    
    private Singleton() {
    }
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
    public static void plusCount() {
        count++;
    }
}

1. 해결방안 : 정적 변수선언에서 인스턴스 생성

  • statice 변수로 싱글톤 인스턴스를 생성한다. 그럼 멀티스레드 환경에서도 다른 객체들은 getInstance를 통해 하나의 인스턴스를 공유할 수 있다.
private static Singleton instance = new Singleton();

2. 해결방안 : synchronized의 사용

  • synchronized를 적용하여 multi-thread 에서의 동시성 문제를 해결하는 방법이다. 하지만 Thread-safe를 보장하기 위해 성능 저하가 발생할 것이다.
public class Singleton {
    public class Singleton {
        private static Singleton instance;

        private Singleton() {}
        
        public static synchronzied Singleton getInstance() {
            if(instance  == null) {
                instance  = new Singleton();
            }
            return instance;
        }
    }
}

Reference: https://velog.io/@seongwon97/%EC%8B%B1%EA%B8%80%ED%86%A4Singleton-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80

profile
BE Developer

0개의 댓글