--- 싱글 톤 디자인 패턴 (싱글 톤) 모드

디자인 패턴 싱글 톤 패턴은 간단하고 가장 일반적으로 사용되는 디자인 패턴입니다. 당신이 정말로 알고 있습니까?
배고픈 사람, 당신이 알고있는 것을 장점과 단점의 차이는 무엇 게으른 남자 스타일?
이 두 가지 외에도 ? 쓰기의 종류, 사실, 또한, 정적 내부 클래스, 당신은 알고 이동을 열거함으로써 달성 될 수있다
다음을 읽어 보시기 바랍니다 더 알아 :

싱글 : 클래스의 인스턴스를 하나만 확인하고 글로벌 액세스 포인트를 제공합니다.

장점과 단점의 A. 단일 예

1. 장점

(1) 유일한 인스턴스에 대한 액세스를 제어 제공
시스템 메모리에 하나의 객체가 있기 때문에 당신은 시스템 리소스를 절약 할 수 있도록, 자주 생성하고 파괴하는 개체 싱글 톤 패턴은 확실히 시스템 성능을 향상시킬 수있는 몇 가지 필요 (2) ,
(3) 본 실시 예 모드, 멀티 모드 실시 예에서 제작 한 실시 형태의 듀얼 모드에 기초하여 확장 될 수있는 실제의 필요에 따라,

2. 단점

코드가 너무 복잡 할 수 너무 무거운 싱글 (1) 기능, 어느 정도 "단일 책임 원칙"에 위배.
장시간 객체의 인스턴스가 아닌 사용하는 경우 (2)에서, 시스템은 물체의 상태가 손실 될 것이다 수집되는 가비지 고려한다.

II. 구현

단일 모드의 실시 예를 달성하기 위해 여러 가지 현장의 요구에 따라, 두 개의 카테고리 6 구현들로 분할 될 수있다. 다음 (보기를 확대하려면 이미지를 클릭)
그림 삽입 설명 여기

싱글 만들기 (I)가 초기화된다

1. 배고픈 중국 스타일

(1) 본 실시 예는 하나의 간단한 구현

(2) 원리 : 스레드 안전 한번만 생성 될 싱글을 보장 의존성 JVM 클래스 로딩기구.

  • (클래스가로드, 즉 후, 스레드 사용하기 전에이) JVM 클래스 초기화 초기화 단계 동안, 같은 수행
  • 초기화 실행 클래스 중, JVM은 잠금을 얻을로 이동합니다. 잠금은 동일한 클래스의 다중 스레드를 초기화 동기화 될 수있다

(3) 코드 구현 :

代码片1
public class Singleton {
 
        // 1. 创建私有变量 ourInstance(用以记录 Singleton 的唯一实例)
       //  2. 内部进行实例化
        private static Singleton instance = new Singleton();

        //3. 把类的构造方法私有化,不让外部调用构造方法实例化
        private Singleton() {

       //4. 定义公有方法提供该类的全局唯一访问点
       //5. 外部通过调用getInstance()方法来返回唯一的实例
        public static Singleton getInstance() {
             return instance;
        }
    }

(4) 응용 시나리오
하나의 예외가 생성 싱글 초기화하는 경우를 제외하고는 밖으로 연장 계속 : 단일 객체 빠른 초기화 및 소형 메모리를 요구한다 .

2. 열거 형

유형을 열거 특성 (1)에있어서, 싱글 요구 충족 싱글을 생성 스레드 안전, 간단 수요 달성

다음 (2) 코드 :

代码片2
public enum Singleton {
    //定义1个枚举的元素,即为单例类的1个实例
    INSTANCE;

    public void test() {
        //do something
    }
}

(3)이 가장 간단하고 쉬운 구현 싱글은, 차용 "효과적인 자바"단어 :
열거 형 단일 요소는 싱글 톤을 달성하는 가장 좋은 방법이되고있다.

(II)는 필요에 따라, 단일 위상차 예를 만드는

3. 게으른 사람의 (기본이되는 구현)

굶주리는 식 (1) 큰 차이가 있다 : 하나의 경우를 생성 할 수있는 기회

  • 굶주리는 유형 : 하나의 예는 클래스가로드 될 때입니다, 기회가 제어 할 수없는 생성 생성 자동으로 싱글을
  • 게으른 유형 : 하나의 예는이 필요할 때, 그냥 제어 타이밍을 생성 수동으로 만들 싱글을

(2) 코드 구현 :

代码片3
class Singleton {
    // 1. 类加载时,先不自动创建单例
   //  即,将单例的引用先赋值为 Null
    private static  Singleton ourInstance  = null;

    // 2. 构造函数 设置为 私有权限
    // 原因:禁止他人创建实例 
    private Singleton() {
    }
    
    // 3. 需要时才手动调用 newInstance() 创建 单例   
    public static  Singleton newInstance() {
    // 先判断单例是否为空,以避免重复创建
    if( ourInstance == null){
        ourInstance = new Singleton();
     }
     return ourInstance;
    }
}

(3) 단점이
재단 게으른 사람이 스레드로부터 안전하지 않습니다, 다음과 같은 이유로 (확대보기로 이미지를 클릭) 달성 :
그림 삽입 설명 여기
쓰기의 게으른 스타일의 기초를 달성하기 위해 솔루션의 다음과 같은 두 가지 종류가 아래로보고 계속합니다.

4. 젠록 (화학식 개선 지연)

(1)의 원리에
따라서 하나의 경우를 피하기 위해, 복수의 스레드가 동시에 호출 않도록 로크의 단일 예를 만드는 방법은 동기화 된 동기 락을 사용하여 만들 반복했다

  • 즉, 블록의 getInstance () 메소드는 스레드를 실행할 수있다
  • 세그먼트 코드가 스레드에서 실행중인 경우, 다른 스레드의 시도는, 그것이 될 코드 블록을 실행 차단 기다려야
  • 그리고,이 단일 사건의 생성을 달성 스레드 안전 방법에서, 단일 객체 모드 및 멀티 스레드 고유성 있도록

다음 (2) 코드 :

// 写法1
class Singleton {
    // 1. 类加载时,先不自动创建单例
    //  即,将单例的引用先赋值为 Null
    private static  Singleton ourInstance  = null;
    
    // 2. 构造函数 设置为 私有权限
    // 原因:禁止他人创建实例 
    private Singleton() {
    }
    
    // 3. 加入同步锁
    public static synchronized Singleton getInstance(){
        // 先判断单例是否为空,以避免重复创建
        if ( ourInstance == null )
            ourInstance = new Singleton();
        return ourInstance;
   }
}


// 写法2
// 该写法的作用与上述写法作用相同,只是写法有所区别
class Singleton{ 

    private static Singleton instance = null;

    private Singleton(){
    }

    public static Singleton getInstance(){
        // 加入同步锁
        synchronized(Singleton.class) {
            if (instance == null)
                instance = new Singleton();
        }
        return instance;
    }
}

(3) 결점
각 구경은 과도한 오버 헤드 동기화 결과, 스레드 동기화 (즉, 로크를 동기화 호출) 실시한다 (= 로크 시간이 걸리는, 에너지 소비).

PS이 : 사실 단지 동기화를위한 필요가 없다, 싱글이 생성되면 메소드가 처음 호출 한 경우에만 동기화 할 필요가있다.

이중 체크 로크 (화학식 개선 지연)

(1)原理
在同步锁的基础上,添加1层 if判断:首先检查实例已经被创建了,如果尚未创建,"才"进行同步,若单例已创建,则不需再执行加锁操作就可获取实例(===>即:只有第一次会同步),从而提高性能。

(2)代码实现:

public class Singleton2 {
    
    private volatile static Singleton2 ourInstance = null;

    private Singleton2() {
    }

    public static Singleton2 newInstance() {
        // 加入双重校验锁
        // 校验锁1:第1个if
        if (ourInstance == null) {  // ①
            synchronized (Singleton2.class) { // ②
                // 校验锁2:第2个 if
                if (ourInstance == null) {
                    ourInstance = new Singleton2();
                }
            }
        }
        return ourInstance;
    }

    // 说明
    // 校验锁1:第1个if
    // 作用:若单例已创建,则直接返回已创建的单例,无需再执行加锁操作
    // 即直接跳到执行 return ourInstance

    // 校验锁2:第2个 if 
    // 作用:防止多次创建单例问题
    // 原理
    // 1. 线程A调用newInstance(),当运行到②位置时,此时线程B也调用了newInstance()
    // 2. 因线程A并没有执行instance = new Singleton();,此时instance仍为空,因此线程B能突破第1层 if 判断,运行到①位置等待synchronized中的A线程执行完毕
    // 3. 当线程A释放同步锁时,单例已创建,即instance已非空
    // 4. 此时线程B 从①开始执行到位置②。此时第2层 if 判断 = 为空(单例已创建),因此也不会创建多余的实例
}

其中第2行代码的java关键字volatile 简单说明一下:
volatile关键字确保,当ourInstance 变量被初始化成Singleton2 实例时,多个线程正确地处理ourInstance 变量。

当性能是你关注的重点,这种写法就可以大大帮你介绍newInstance的时间消耗。

(3)缺点:
没什么明显缺点,就写法有点复杂,容易出错。

6. 静态内部类

(1)原理
根据 静态内部类 的特性,同时解决了按需加载、线程安全的问题,同时实现简洁

  • 在静态内部类里创建单例,在装载该内部类时才会去创建单例。
  • 线程安全:类是由 JVM加载,而JVM只会加载1遍,保证只有1个单例。

(2)代码实现

public class Singleton3 {
    
    // 1. 创建静态内部类
    private static class SingleTonHoler{
        // 在静态内部类里创建单例
        private static Singleton3 INSTANCE = new Singleton3();
    }

    // 私有构造函数
    private Singleton3(){}

    // 延迟加载、按需创建
    public static Singleton3 getInstance(){
        return SingleTonHoler.INSTANCE;
    }
}

// 调用过程说明:
// 1. 外部调用类的getInstance 
// 2. 自动调用SingleTonHoler.INSTANCE
// 2.1 此时单例类Singleton3得到初始化
// 2.2 而该类在装载 & 被初始化时,会初始化它的静态域,从而创建单例;
// 2.3 由于是静态域,因此只会JVM只会加载1遍,Java虚拟机保证了线程安全性
// 3. 最终只创建1个单例

(3)缺点:
静态内部类有一个致命的缺点,就是传参的问题,由于是静态内部类的形式去创建单例的,故外部无法传递参数进去,例如Context这种参数,所以,我们创建单例时,可以在静态内部类与DCL模式里自己斟酌。

关于静态内部类创建单例模式,推荐大家阅读以下文章,可以更加深入的理解:
深入理解单例模式:静态内部类单例原理

三.总结:

本文主要对 单例模式 进行了全面介绍,包括原理 & 实现方式。对于实现方式,此处作出总结(图片点击可放大查看):
그림 삽입 설명 여기

게시 81 개 원래 기사 · 원 찬양 37 ·은 50000 +를 볼

추천

출처blog.csdn.net/gaolh89/article/details/93235424