zoukankan      html  css  js  c++  java
  • 单例模式

     私有构造函数、私有静态变量以及 公有静态函数

    几种形式:

    1 懒汉式(不安全)

    不使用时不加载

    public class Singleton {
        private static Singleton instance;
    
        private Singleton() {
        }
    
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    
    }

    2 饿汉 安全

    public class Singleton {
        private static Singleton instance = new Singleton();
        private Singleton() {
        }
        public static Singleton getInstance() {
            return instance;
        }
    }

     3 懒汉式 线程安全

    加锁方式 不推荐使用

    public class Singleton {
        private static Singleton instance;
        private Singleton() {
        }
        public static synchronized Singleton getInstance() {
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }

    4 双重检查锁 线程安全

    只对实例化的部分代码进行加锁

    考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程都执行了 if 语句,那么两个线程都会进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton(); 这条语句,只是先后的问题,那么就会进行两次实例化。因此必须使用双重校验锁,也就是需要使用两个 if 语句。

    uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:

    1. 为 uniqueInstance 分配内存空间
    2. 初始化 uniqueInstance
    3. 将 uniqueInstance 指向分配的内存地址

    但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1>3>2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。

    使用 volatile 关键字为了防止指令重排

     5 静态内部类实现

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

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

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

    6 枚举方法实现

    两个 hashcode 是相同的

    public enum Singleton {
        INSTANCE;
        private String objName;
    
        public void setObjName(String name) {
            this.objName = name;
        }
    
        public static void main(String[] args) {
            Singleton s1 = Singleton.INSTANCE;
            s1.setObjName("first instance");
            System.out.println(s1.objName);
            System.out.println(s1.hashCode());
            Singleton s2 = Singleton.INSTANCE;
            s2.setObjName("second instance");
            System.out.println(s2.objName);
            System.out.println(s2.hashCode());
            try
    
            {
                Singleton[] enumConstants = Singleton.class.getEnumConstants();
                for (Singleton enumConstant : enumConstants) {
                    System.out.println(enumConstant.objName);
                }
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    K8S 使用NFS 创建PV和PVC的例子 学习From https://blog.csdn.net/xts_huangxin/article/details/51494472
    Windows 2012r2 以及以上版本远程提示错误的解决方法
    CentOS下 NFS的简单使用以及windows 关在linux的NFS存储方法
    PPT 遥控器
    Windows 下面简单的同步文件夹工具
    IIS 下 搭建简单的FTP服务器
    Zoom 会议系统
    SQLSERVER 2014 内存优化表相关
    SQLSERVER 2014 SP1 的服务器 日志文件无法收缩的处理
    Jenkins Jfrog Artifactory 以及docker下的pipeline 容器编排实践
  • 原文地址:https://www.cnblogs.com/zhy-study/p/10651278.html
Copyright © 2011-2022 走看看