자바 싱글 톤 디자인 패턴 여덟 가지 방법

싱글 톤 디자인 패턴 소개

클래스라는 싱글 톤 디자인 패턴은 객체 인스턴스의 특정 클래스가 전체 소프트웨어 시스템을 보장하기 위해 어떤 방법을 취할이며, 클래스는 객체 인스턴스를 얻기 위해 하나의 방법 (정적 방법)를 제공합니다.
이러한 Hibernate의 SessionFactory를, 그것은 프록시 데이터 저장 소스의 역할을하고, 세션 객체를 생성하는 책임이있다. SessionFactory를하지 경량, 정상적인 상황에서, 프로젝트는 일반적으로이 싱글에 사용됩니다됩니다 만 SessionFactory에 충분해야합니다.

싱글 톤 디자인 패턴 여덟 가지 방법

패턴 싱글 여덟 가지 방법이 있습니다 :

  1. 배고파 화학식 ((정적 CONST))
  2. 배고파 화학식 (정적 코드 블록)
  3. 게으른 사람의 (스레드 안전)
  4. 게으른 남자의 (스레드 안전, 동기화 방법)
  5. 지연 식 (스레드 안전 동기화 블록)
  6. 두 번 검사
  7. 정적 내부 클래스
  8. 열거

1. 배고파 화학식 (정적 상수)

배고픈 사람의 유형 (정적 상수) 애플리케이션 예제

다음 단계 :

1) 민영화 생성자 () 방지 새로운
객체 클래스를 생성하는) 2 내부
3) 외측 공용 정적 메소드를 노출한다. 의 getInstance

코드 구현

class SingletonTest01 {

    public static void main(String[] args) {
        //测试
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

//饿汉式(静态变量)

class Singleton {

    //1. 构造器私有化, 外部能new
    private Singleton() {

    }

    //2.本类内部创建对象实例
    private final static Singleton instance = new Singleton();

    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }

}

장점과 단점을 설명합니다 :

  1. 장점 : 이러한 접근 방식은 로딩이 클래스가 인스턴스화 완료되면, 즉, 상대적으로 간단하다. 스레드 동기화 문제를 방지합니다.
  2. 단점 : 클래스가 로딩이 완료 될 때 인스턴스화 될 때, 효과가 게으른로드에 도달하지 않았다. 당신이 처음부터 끝까지이 예제를 사용하지 않은 경우, 그것은 메모리의 낭비가 발생합니다
  3. classloder 메커니즘을 기반으로 이러한 방법으로 동기화 문제 멀티 스레딩은, 그러나, 그러므로 수없는 클래스의 인스턴스에 인스턴스 대부분의 경우 단일 모드 getInstance 메소드를 호출 시간에로드하지만, 클래스가로드되는 몇 가지 이유가 있습니다, 및 방지 클래스 로더의 원인을 결정하는 다른 방법 (또는 다른 정적 방법)이있다, 그것은 게으른 로딩 효과 초기화 인스턴스를 도달하지 않을 것이다

결론 :

본 실시 형태는 단독으로 사용할 수도 있고, 메모리는 낭비 될 수도


2. 배고파 화학식 (정적 코드 블록)

코드 구현

package com.jfjb.singleton.type1;

class SingletonTest01 {

    public static void main(String[] args) {
        //测试
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

//饿汉式(静态变量)

class Singleton {

    //1. 构造器私有化, 外部能new
    private Singleton() {

    }

    //2.本类内部创建对象实例
    private  static Singleton instance;

    static { // 在静态代码块中,创建单例对象
        instance = new Singleton();
    }

    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }

}

장점과 단점을 설명합니다 :

  1. 이와 같이 상기 방식과 실제로 매우 유사 코드 블록 정적 코드, 예 초기화 클래스를 실행하는 클래스의 처리는 클래스가로드 된 정적 코드 블록 인스턴스화되는 것을 제외. 장점과 단점 및 위는 동일합니다.

    결론 :

    이 단일 사례 가능한 모델,하지만 메모리 낭비가 발생할 수 있습니다


3. 게으른 사람의 (스레드 안전)

코드 구현

class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("懒汉式1 , 线程不安全~");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

class Singleton {
    private static Singleton instance;

    private Singleton() {}

    //提供一个静态的公有方法,当使用到该方法时,才去创建 instance
    //即懒汉式
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

장점과 단점을 설명합니다 :

  1. 게으른로드 효과를 연주하지만 단일 스레드에서 사용할 수 있습니다.
  2. 멀티 스레드 경우, 경우 (싱글 == NULL) 분석 문 블록으로 스레드가 내려 수행하는 시간이 있었다, 또한 시간 인스턴스의 복수 생산할 예정이 문장 분석 다른 스레드. 그래서 다중 스레드 환경에서이 방법을 사용할 수 없습니다

결론 :

실제 개발에서,이 방법을 사용하지 마십시오.


4. 한 레이지 식 (스레드 안전 동기화 방법)

코드 구현

public class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("懒汉式2 , 线程安全~");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

// 懒汉式(线程安全,同步方法)
class Singleton {
    private static Singleton instance;

    private Singleton() {}

    //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

장점과 단점을 설명합니다 :

1) 불안 스레드의 문제를 해결하기 위해
너무 낮은 2) 효율성을하고, 방법은 동기화해야합니다 ()의 getInstance를 구현하기 위해 수업 시간의 각 스레드 인스턴스에 싶어. 그리고 사실, 코드의 인스턴스가 충분하다이 방법 만하면, 나는 라인에 인스턴스를 직접 리턴 이런 종류의 뒤에 싶어. 동기화에 비효율적 인 방법

결론 :

실제 개발에서,이 방법으로 사용하지 않는 것이 좋습니다


5. 한 레이지 식 (스레드 안전 동기화 블록)

코드 구현

// 懒汉式(线程安全,同步代码块)
class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

장점과 단점을 설명합니다 :

1) 이와 같이 인스턴스화 동기 부호 블록을 생성하기 위해 너무 낮은 효율로 제 전면 동기화 방법의 구현을 개선하고자 하였다
) (2) 그러나, 그러한 동기화 스레드 동기화의 역할을 할 수 없다 . 스레드가있는 경우 (싱글 톤 == null이) 판단 문 블록 아래로 실행하기 위해 충분한 시간을 입력하면 세 번째 시나리오는, 구현 경험과 일치, 또한 판사 문장을 통과 다른 스레드가이 시간이 생성됩니다 여러 인스턴스

결론 :

실제 개발에서,이 방법을 사용할 수 없습니다


6. 한 번 확인 (권장)

코드 구현

public class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("双重检查");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());

    }

}

// 懒汉式(线程安全,同步方法)
class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
    //同时保证了效率, 推荐使用

    public static synchronized Singleton getInstance() {
        if(instance == null) {
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }

        }
        return instance;
    }
}

장점과 단점을 설명합니다 :

코드에서와 같이 1)을 두 번 확인 개념은 종종 멀티 스레드 개발하는 데 사용됩니다, 우리는 보안 스레드를 보장하기 때문에로,이 경우 (싱글 == NULL) 검사를 실시했다.
. 이후 다시 액세스 할 때 (싱글 == NULL)이 직접 복귀 객체 인스턴스는, 상기 방법은 반복 된 동기화를 피할 수있는 경우 2) 따라서 인스턴스화 코드 번만이를 판정
지연 로딩; 3) 보안 스레드보다 효율적 높은

결론 :

실제 개발에서, 이것은 디자인 패턴 싱글 추천


7. 정전기 내부 클래스 (권장)

코드 구현

public class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("使用静态内部类完成单例模式");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());

    }

}

// 静态内部类完成, 推荐使用
class Singleton {
    private static volatile Singleton instance;

    //构造器私有化
    private Singleton() {
    }

    //写一个静态内部类,该类中有一个静态属性 Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
    public static synchronized Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

장점과 단점을 설명합니다 :

1) 这种方式采用了类装载的机制来保证初始化实例时只有一个线程。
2) 静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
3) 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
4) 优点:避免了 线程不安全,利用静态内部类特点实现延迟加载,效率高

结论:

推荐使用.


8. 枚举(推荐)

代码实现

public class SingletonTest01 {
    public static void main(String[] args) {
        Singleton instance = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;
        System.out.println(instance == instance2);

        System.out.println(instance.hashCode());
        System.out.println(instance2.hashCode());

        instance.sayOK();
    }
}

//使用枚举,可以实现单例, 推荐
enum Singleton {
    INSTANCE; //属性
    public void sayOK() {
        System.out.println("ok~");
    }
}

优缺点说明:

1) 这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
2) 这种方式是Effective Java作者Josh Bloch 提倡的方式

结论:

推荐使用


在JDK 应用的源码分析

我们JDK中,java.lang.Runtime就是经典的单例模式(饿汉式)

单例模式注意事项和细节说明

1) 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
2) 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new
3) 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)


参考基于尚硅谷Java设计模式,韩顺平图解java设计模式

추천

출처www.cnblogs.com/ifme/p/12433324.html