java 디자인 모델의 단례 모델

4024 단어 java단일 모드
java 디자인 모델의 단례 모델
선언:
소프트웨어 개발 과정에서 우리는 라인 탱크(threadpool), 캐시(cache), 대화상자, 선호 설정 등 하나만 필요로 하는 대상이 종종 있다.이러한 대상이 여러 개의 실례를 만들면 프로그램 행위 이상, 자원 과다 사용 등 불필요한 번거로움을 초래할 수 있다.이 때 단일 모드는 하나의 클래스가 하나의 실례만 있고 전역 접근점을 제공할 수 있다.다음은 간단한 단례류에서 어떤 방법으로 단례모델을 실현해야 하는지를 연구하고자 한다.

/**
 *  
 */
public class Singleton {
  //  Singleton 
  private static Singleton singleInstance;
  private Singleton(){
    //  , Singleton 
  }
  /*
   *  Singleton , 
   */
  public static Singleton getInstance(){
    if (singleInstance == null) {
      singleInstance = new Singleton();
    }
    return singleInstance;
  }
  //  
}
위의 예에서 볼 수 있듯이 Singleton 클래스는 이 클래스의 실례화 과정을 스스로 관리하고 전역 접근점을 제공합니다. 정적 get Instance () 방법으로 설정하여 다른 클래스가 Singleton을 사용할 때 하나의 실례를 되돌려줍니다.이 단례 모델의 장점은 바로 지연 실례화이다. 간단하게 말하면 지연 실례화는 지연 초기화이다. 클래스가 필요할 때 그 실례를 만드는 것이지 이 클래스를 불러오기 시작할 때 실례를 만드는 것이 아니다. 이런 장점은 성능의 낭비를 피할 수 있다는 것이다.예를 들어 어떤 대상은 프로그램이 처음부터 사용하지 않거나 프로그램이 실행되는 과정에서 사용하지 않았다.그러나 이 예는 또 하나의 단점이다. 그것은 바로 라인이 안전하지 않다는 것이다.만약에 여러 개의 라인이 get Instance () 방법에 동시에 실행되고 Singleton이 new Singleton () 하나의 실례가 없다면 라인은 모두single Instance를null로 생각하고 모두 Singleton을 실례화하기 때문에 여러 개의 Singleton 실례가 발생하여 단일 모델의 취지에 현저히 부합되지 않기 때문이다.그럼 다음에 할 수 있는 건 개선하는 거예요.

public class SingletonA {
  private static SingletonA singletongA;
  private SingletonA(){

  }
  /*
   *  synchronized getSingletonA 
   */
  public static synchronized SingletonA getInstanceA(){
    if (singletongA == null) {
      singletongA = new SingletonA();
    }
    return singletongA;
  }
  //  
}

이 예에서 볼 때synchronized를 추가하면 get Instance A () 를 동기화 방법으로 만들 수 있습니다. 이 방법은 이 방법에 들어가기 전에 다른 라인이 이 방법을 떠나야만 들어갈 수 있습니다. 또한 이 방법은 하나의 라인만 동시에 존재할 수 있습니다.
문제가 많지 않을 수도 있지만, 동기화 방법은 프로그램의 실행 효율에 영향을 미칠 수 있다는 것을 알아야 한다. 이 예에서 우리는 첫 번째 예에서 getInstance () 방법을 처음 실행하는 것을 해결하기 위해 여러 개의 실례를 만들지 않을 뿐이다. 이 예에서는 실례가 필요할 때마다 get Instance A () 동기화 방법을 호출하지만, 이미 실례가 있는 후에synchronized를 호출하는 것은 군더더기가 된다.이 단례류가 다시 새로운 실례를 만들어낼까 봐 걱정할 필요가 없기 때문이다.그래서 우리는 개선을 해야 한다.
위에서 실례화 지연을 말한 이상 사용하지 않는다면 훨씬 간단하다.

public class SingletonB {
  //  (static initializen) , 
  private static SingletonB singletonB = new SingletonB();
  private SingletonB(){
    //  
  }
  public static SingletonB getInstaceB(){
    //  , 
    return singletonB;
  }
}
위의 방법은 JVM이 이 클래스를 불러올 때 바로 실례를 만드는 것입니다. 왜냐하면 JVM은 이 실례에 접근하기 전에 이 실례를 만들기 때문에 실례는 안전합니다.그러나 이는 실례화 지연에 비해 자원의 낭비가 발생할 수 있다.그리고 이런 큰 경우 프로그램 초기화 시간이 길어집니다.
그러면 지연 실례화를 사용하는 동시에 라인이 안전하지 않고 방문 효율을 높일 수 있을까요?다음은 이중 검사와 자물쇠로 개선하겠습니다.

/**
 *  
 */
public class SingletonC {
  private volatile static SingletonC singletonC;
  private SingletonC(){

  }
  public static SingletonC getInstanceC(){
    if (singletonC == null) {
      synchronized (SingletonC.class) {
        if (singletonC == null) {
          singletonC = new SingletonC();
        }
      }
    }
    return singletonC;
  }
}

위의 예는 실례를 먼저 검사하고 존재하지 않으면 동기화 블록에 들어가고 동기화 블록에 들어간 후에 다시 검사합니다. 만약null이 있어야 실례를 만들 수 있기 때문에 singletonC = new SingletonC () 는 한 번만 실행하고 그 다음에 get InstanceC () 를 호출할 때 실례가 있기 때문에 첫 번째 호출을 제외하고는 동기화를 합니다. 그 다음에 두 번째 예처럼 매번 동기화 방법을 하지 않습니다.이렇게 하면 getInstanceC()를 실행하는 시간을 줄일 수 있습니다.틀림없이 여기에volatile 키워드가 발견될 것이다. 그 역할은 singletonC가 초기화된 후에 모든 라인을 볼 수 있도록 하는 것이다. 여러 개의 라인이 이 SingletonC 변수를 정확하게 처리할 수 있다.그러나 주의해야 할 것은volatile 키워드는 자바 5와 그 후에만 사용할 수 있으며, 이 버전 이전에는 이중 검사가 효력을 상실할 수 있습니다.
단일 모드를 사용할 때, 여러 개의 클래스 로더 (classloader) 가 있을 때, 클래스 로더를 스스로 지정하고, 클래스 로더를 지정해야 합니다.모든 클래스 마운트는 하나의 이름 공간을 정의하기 때문에, 서로 다른 클래스 마운트는 같은 클래스를 마운트하여 하나의 클래스가 여러 개의 실례를 만들 수 있습니다.
읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기