43°

设计模式 单例模式

单例模式作为设计模式中做常见的一种,这里代码也不重复了。

单例模式有9种实现方式,但是其中部分是有缺陷的。总结下来就是四种:

一、饿汉模式

/**
 * @ClassName: Singleton2
 * @description: 单例模式---饿汉模式(线程安全,但是不节省资源)
 * @author: edison_Kwok
 * @Date: create in 2019/12/10 22:59
 * @Version: 1.0
 */
public class Singleton2 {
private static Singleton2 uniqueSingleton2 = new Singleton2();

private Singleton2() {
}

public static Singleton2 getUniqueSingleton2() {
    //线程不安全问题主要是由于 uniqueInstance 被实例化多次,采取直接实例化 uniqueInstance 的方式就不会产生线程不安全问题。
    //但是直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。
    return uniqueSingleton2;
}

}

二、双重校验的懒汉模式

/**
 * @ClassName: Singleton4
 * @description: 单例模式---懒汉模式(双重校验锁-线程安全)
 * @author: edison_Kwok
 * @Date: create in 2019/12/10 23:09
 * @Version: 1.0
 */
public class Singleton4 {
//uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:
//
//为 uniqueInstance 分配内存空间
//初始化 uniqueInstance
//将 uniqueInstance 指向分配的内存地址

//使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
private volatile static Singleton4 uniqueSingleton4;

private Singleton4() {
}

//uniqueInstance 只需要被实例化一次,之后就可以直接使用了。
// 加锁操作只需要对实例化那部分的代码进行,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。
//双重校验锁先判断 uniqueInstance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。
public static Singleton4 getUniqueSingleton4() {
    if (uniqueSingleton4 == null) {
        synchronized (Singleton4.class) {
            if (uniqueSingleton4 == null) {
                //如果不加上里面这个null判断,可能就会出现两个线程在次等待
                //两个线程都执行new命令
                uniqueSingleton4 = new Singleton4();
            }
        }
    }
    return uniqueSingleton4;
}

}

三、内部类

/**
 * @ClassName: Singleton5
 * @description: 静态内部类实现
 * @author: edison_Kwok
 * @Date: create in 2019/12/10 23:18
 * @Version: 1.0
 */
public class Singleton5 {
private Singleton5() {
}

//当 Singleton 类被加载时,静态内部类 SingletonHolder 没有被加载进内存。
private static class Singleton5Holder {
    //只有当调用 getUniqueInstance() 方法从而触发 SingletonHolder.INSTANCE 时 SingletonHolder 才会被加载
    // 此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。
    private static final Singleton5 uniqueSingleton5 = new Singleton5();
}

public static Singleton5 getUniqueSingleton5() {
    //这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持。
    return Singleton5Holder.uniqueSingleton5;
}

}

四、枚举形式(大佬推荐)

/**
 * @ClassName: Singleton6
 * @description:
 * @author: edison_Kwok
 * @Date: create in 2019/12/22 20:32
 * @Version: 1.0
 */
public enum Singleton6 {
    instance;
}

class Client{ public static void main(String[] args) { Singleton6 instance = Singleton6.instance; } }

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

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

六、单例模式在JDK源码

jdk中的java.lang.Runtime类

本文由【edison_kwok】发布于开源中国,原文链接:https://my.oschina.net/edisonOnCall/blog/3145976

全部评论: 0

    我有话说: