前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 单例模式 Singleton

Java 单例模式 Singleton

作者头像
Tim在路上
发布2020-08-05 00:14:16
3240
发布2020-08-05 00:14:16
举报

单例

单例的目的是确保一个类只有一个实例,并提供该实例的全局访问点。

  • [类]

使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。

懒汉式-线程不安全

懒汉式-单例,静态变量被延迟实例化,这样做的好处是节约资源,但是在多线程下,因为多线程同时进入if (uniqueInstance == null) ,并且此时 uniqueInstance 为 null,那么会有多个线程执行uniqueInstance = new Singleton(); 语句,这将导致实例化多次 uniqueInstance。

代码语言:javascript
复制
public class Singleton {
    private static Singleton unqueInstance = null;
    //私有构造函数
    private  Singleton(){

    }
    public static  Singleton getUnqueInstance(){
            if(unqueInstance==null){
                unqueInstance = new Singleton();
            }
            return unqueInstance;
    }
}

懒汉式-线程安全

线程不安全的原因是多个线程同时进入了共有静态函数中的if代码块里,所以只要在共有静态函数上加一个同步锁就可以防止这样的情况。

代码语言:javascript
复制
public class Singleton {
    private static Singleton unqueInstance = null;
    //私有构造函数
    private  Singleton(){

    }
    public static synchronized Singleton getUnqueInstance(){
            if(unqueInstance==null){
                unqueInstance = new Singleton();
            }
            return unqueInstance;
    }
}

但是其实这样笼统的修改会影响效率的问题,比如当unqueInstance不等于null的时候,应该直接返回,但是此时unqueInstance==null和unqueInstance!=null同时访问该方法,这会让线程阻塞时间过长,因此该方法有性能问题。

饿汉式-线程安全

代码语言:javascript
复制
public class Singleton {
    private static Singleton unqueInstance = new Singleton();
    //私有构造函数
    private  Singleton(){

    }
    public static  Singleton getUnqueInstance(){
            return unqueInstance;
    }
}

直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。

双重校验锁-线程安全

这个是对懒汉式线程安全的进一步改进,就像我们在之前的描述一样,线程不安全的原因是多个线程同时进入了共有静态函数中的if代码块里,我们只需要对if代码块加入同步锁,但是如果两个线程都执行了 if 语句,那么两个线程都会进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton(); 这条语句,只是先后的问题,那么就会进行两次实例化。因此必须使用双重校验锁,也就是需要使用两个 if 语句。

代码语言:javascript
复制
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;
    }
}

静态内部类实现

当 Singleton 类加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 getUniqueInstance() 方法从而触发 SingletonHolder.INSTANCE 时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。

这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持。

代码语言:javascript
复制
public class Singleton {

    private  Singleton(){
    }

    private  static  class SingletonHolder{
        private  static  final  Singleton INSTANCE = new Singleton();
    }

    public static  Singleton getUniqueInstance(){
        return  SingletonHolder.INSTANCE;
    }
}

枚举实现

代码语言:javascript
复制
public enum Singleton {

    INSTANCE;

    private String objName;


    public String getObjName() {
        return objName;
    }


    public void setObjName(String objName) {
        this.objName = objName;
    }


    public static void main(String[] args) {

        // 单例测试
        Singleton firstSingleton = Singleton.INSTANCE;
        firstSingleton.setObjName("firstName");
        System.out.println(firstSingleton.getObjName());
        Singleton secondSingleton = Singleton.INSTANCE;
        secondSingleton.setObjName("secondName");
        System.out.println(firstSingleton.getObjName());
        System.out.println(secondSingleton.getObjName());

        // 反射获取实例测试
        try {
            Singleton[] enumConstants = Singleton.class.getEnumConstants();
            for (Singleton enumConstant : enumConstants) {
                System.out.println(enumConstant.getObjName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例
    • 懒汉式-线程不安全
    • 懒汉式-线程安全
    • 饿汉式-线程安全
    • 双重校验锁-线程安全
    • 静态内部类实现
    • 枚举实现
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档