• 单例模式:饿汉式和懒汉式的实现


    先列举最常见的单例模式:

    一:饿汉式

    1、直接创建适合简单的单例模式:

    public class SingleTon{
       private static SingleTon INSTANCE = new SingleTon();
       private SingleTon(){}
       public static SingleTon getInstance(){ return INSTANCE; }}

     2、适合需要较复杂的初始化的单例模式:

    public class SingleTon{
       private final static SingleTon INSTANCE ;
        private String info;
        static {
            //初始化参数
        }
        private SingleTon(String info){
            this.info = info;
        }
       public static SingleTon getInstance(){ return INSTANCE; }}        

    二:懒汉式

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

    此方法线程不安全

    1、双锁检验懒汉式

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

    此方法看似解决了线程安全问题,实际上还存在隐患,可能出现线程a还在初始化instance但未完全初始化时,线程b就通过instance!=null判断返回了这个instance对象。

    这是由于JVM的重排序,导致instance已经指向了一块内存,但这块内存并没有初始化。其根本原因是对象实例化不是原子操作,其顺序可能被重排,可分为三步:

    • 1.分配一块内存空间
    • 2.在这块内存上初始化一个DoubleCheckLock的实例
    • 3.将声明的引用instance指向这块内存

    具体原因可参考:https://blog.csdn.net/zy13608089849/article/details/82703192

    这里可以给instance加上volatile修饰符禁止jvm重排解决。

    其他线程安全的方法还有:

    2、静态内部类

    public class SingleTon{
      private SingleTon(){}
     
      private static class SingleTonHoler{
         private static SingleTon INSTANCE = new SingleTon();
     }
     
      public static SingleTon getInstance(){
        return SingleTonHoler.INSTANCE;
      }
    }

    由于内部类只会在getInstance()时才会被加载,且只加载一次,因此也可以看作是线程安全的懒汉式

    3、枚举

    public enum Singleton{
    INSTANCE;
    }

    大概是最简单的单例了哈哈

  • 相关阅读:
    zoj 3599 Game 博弈论
    hdu 2486/2580 / poj 3922 A simple stone game 博弈论
    hdu 1517 A Multiplication Game 博弈论
    hdu 4407 Sum 容斥原理
    hdu 4686 Arc of Dream
    hdu 4588 Count The Carries
    hdu 4586 Play the Dice
    C#学习(5)
    C#学习(4)
    C#学习(3)
  • 原文地址:https://www.cnblogs.com/Noctis/p/10519137.html
Copyright © 2020-2023  润新知