其他分享
首页 > 其他分享> > 面试常客:手撕单例模式

面试常客:手撕单例模式

作者:互联网

设计模式、方法等
一.单例模式
1.定义:一个类只能有一个实例,并提供该实例的全局访问点。好处是有些实例在全局中只需要一个,使用单例模式可以避免一个全局使用的类(在自己项目当中就是user类)
2.设计要素
(1)一个私有构造函数
(2)一个私有静态变量
(3)一个公有静态函数
二.懒汉式(线程不安全)
1.先不创建实例,第一次被调用时创建
2.也没有synchronized,所以线程不安全,同时多线程条件下可能会实例化多个实例
3.有点是延迟了实例化,如果不使用该类,就不会被实例化
三.饿汉式(线程安全)
1.不管是否需要,直接实例化好(就像饿死鬼一样),然后需要的时候就直接调用方法
2.因为提前实例化好了,所以不需要考虑线程安全的问题
3.但也因为实例化好了,如果使用,就造成了资源的浪费

public class Singleton {
    private static Singleton uniqueInstance = new Singleton();
    private Singleton() {
    }
    public static Singleton getUniqueInstance() {
        return uniqueInstance;
    }
}

四.双重检查锁实现(线程安全) 突然发现就很顾名思义
1.首先需要检查两次
2.其次用synchronized保证了线程安全
3.相当于改进了的线程安全的懒汉模式,将锁的位置变了并多了一个检查,第一个判断是判断实例是否存在,锁之后的判断是只允许一个线程实例化,这样就只会在第一次的时候有线程阻塞的情况。

public class Singleton {
    
    private volatile static Singleton uniqueInstance;
    
    private Singleton() {
    }
    
    public static Singleton getUniqueInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }  
}

五.为什么要用volatile修饰uniqueInstance
因为新建一个对象分为3步:分配内存空间,初始化对象,将对象指向分配的内存地址;
但是jvm有指令重排的特性,单线程的时候没有问题,但多线程可能会导致有些线程获取没有初始化完成的实例。这时候就需要volatile,它可以禁止jvm的指令重排
六.静态内部类实现(线程安全)
1.外部类Singleton被加载的时候,SingletonHolder并没有被加载 ,调用getxx()方法的时候,才会运行并加载静态内部类,然后初始化实例,此时靠jvm来保证只被实例化一次

public class Singleton {
    
    private Singleton() {
    }
    
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getUniqueInstance() {
        return SingletonHolder.INSTANCE;
    }
     
}

七.枚举类实现

public enum Singleton {
    
    INSTANCE;

    //添加自己需要的操作
    public void doSomeThing() {
    
    }
    
}

八.使用场景
频繁实例化然后又销毁的对象,使用单例模式可以提高性能。
经常使用的对象,但实例化时耗费时间或者资源多,如数据库连接池,使用单例模式,可以提高性能,降低资源损坏。
使用线程池之类的控制资源时,使用单例模式,可以方便资源之间的通信。

标签:Singleton,常客,面试,uniqueInstance,实例,线程,单例,static,public
来源: https://www.cnblogs.com/donkeyAndConcise/p/15085139.html