单例的四种实现方式

一、什么是单例模式?

1、定义

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

从另一个角度来说,Singleton模式其实也是一种职责型模式。因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责

2、单例模式的优点

1)在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例

2)单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。

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

4)由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式 无疑可以提高系统的性能。

5)允许可变数目的实例。

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

3、单例模式的应用场景

单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:

1)需要频繁实例化然后销毁的对象。

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

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

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

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

1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。

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

二、单例的四种实现方式

1、饿汉式

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


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

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

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

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

2、懒汉式(同步方法)

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

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

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

    private static Singleton_two instance = null;

    public synchronized static Singleton_two getInstance() {

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

3、懒汉式(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;
    }
}

4、静态内部类

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;
    }
}

猜你喜欢

转载自www.cnblogs.com/chenyichen/p/10561495.html