单例的四种实现方式

1、什么是单例模式?

一、定义

Singleton模式要求一个类有且仅有一个实例,而且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,因此,这应该是类设计者的责任,而不是类使用者的责任。java

<!--more-->数据库

从另外一个角度来讲,Singleton模式其实也是一种职责型模式。由于咱们建立了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的全部权力,同时它也肩负了行使这种权力的职责安全

二、单例模式的优势

1)在单例模式中,活动的单例只有一个实例,对单例类的全部实例化获得的都是相同的一个实例。这样就 防止其它对象对本身的实例化,确保全部的对象都访问一个实例工具

2)单例模式具备必定的伸缩性,类本身来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。性能

3)提供了对惟一实例的受控访问。spa

4)因为在系统内存中只存在一个对象,所以能够 节约系统资源,当 须要频繁建立和销毁的对象时单例模式 无疑能够提升系统的性能。线程

5)容许可变数目的实例。设计

6)避免对共享资源的多重占用。日志

三、单例模式的应用场景

单例模式只容许建立一个对象,所以节省内存,加快对象访问速度,所以对象须要被公用的场合适合使用,如多个模块使用同一个数据源链接对象等等。如:code

1)须要频繁实例化而后销毁的对象。

2)建立对象时耗时过多或者耗资源过多,但又常常用到的对象。

3)有状态的工具类对象。

4)频繁访问数据库或文件的对象。

如下都是单例模式的经典使用场景:

1)资源共享的状况下,避免因为资源操做时致使的性能或损耗等。如上述中的日志文件,应用配置。

2)控制资源的状况下,方便资源之间的互相通讯。如线程池等

2、单例的四种实现方式

一、饿汉式

饿汉式: 在类装载的时候就急速的初始化,饿汉式是线程安全的、 可是没有延迟加载

/**
 * 饿汉式
 */
class Singleton_one {

    // 一、私有化构造器
    private Singleton_one() {
    }

    // 二、初始化
    private static Singleton_one instance = new Singleton_one();

    public static Singleton_one getInstance() {
        return instance;
    }
}

二、懒汉式(同步方法)

单纯的懒汉式是存在线程安全问题的、须要咱们使用同步策略

/**
 * 懒汉式(同步方法)
 */
class Singleton_two {

    // 一、私有化构造器
    private Singleton_two() {
    }

    private static Singleton_two instance = null;

    public synchronized static Singleton_two getInstance() {

        if (instance == null) {
            instance = new Singleton_two();
        }
        return instance;
    }
}

三、懒汉式(Dubbo Check)

单纯的懒汉式是存在线程安全问题的、须要咱们使用同步策略、这里使用了双重校验

/**
 * 懒汉式(Double Check)
 */
class Singleton_three {

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

    private static Singleton_three instance = null;

    public static Singleton_three getInstance() {

        if (instance == null) {

            synchronized (Singleton_three.class) {

                if (instance == null) {
                    instance = new Singleton_three();
                }
            }
        }
        return instance;
    }
}

四、静态内部类

1)静态内部类的加载时机

  1. 外部类初次加载,会初始化静态变量、静态代码块、静态方法,但不会加载内部类和静态内部类。
  2. 实例化外部类,调用外部类的静态方法、静态变量,则外部类必须先进行加载,但只加载一次。
  3. 直接调用静态内部类时,外部类不会加载。
/**
 * 内部类实现单例模式
 * <p>
 * 既不用加锁 、也能实现懒加载
 *
 *
 * 外部类初次加载的时候不会加载内部类和静态内部类
 */
class Singleton_four {

    private static int a = 10;

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

    private static class Inner {

        static Singleton_four instance = new Singleton_four();
    }

    public static Singleton_four getInstance() {
        return Inner.instance;
    }
}
相关文章
相关标签/搜索