• 单例模式,学习笔记


    一、单例模式实现三要素:

    ●只能有一个实例。
      ◆构造器私有化

    ●自行创建这个实例
      ◆含有一个该类的静态变量来保存这个唯一的实例
    ●必须自行向整个系统提供这个实例;
      ◆对外提供获取该实例对象的方式:
      (1)直接暴露

      (2)用静态变量的get方法获取

    二、单例模式分类

    根据对象创建的时机不同,单例模式可以分为两类。一种是在类初始化的时候直接创建对象,称为饿汉式;另一种是在调用类静态方法时才创建对象,称为懒汉式。

    三、饿汉式

    饿汉式是线程安全的。

    1.直接实例化饿汉式

    public class Singleton {
        public static final Singleton INSTANCE = new Singleton();  //final修饰,强调这是一个单例
        private Singleton(){}
    
    }

     2.枚举类饿汉式

    public enum Singleton {
        INSTANCE;
    }

    3.静态代码块方式

    public class Singleton {
        public static final Singleton INSTANCE;  //final修饰,强调这是一个单例
        static {
            INSTANCE = new Singleton();
        }
        private Singleton(){}
    
    }

     这种方式适合于需要通过加载外部文件,来实例化单例对象属性的时候。

    例如:

    public class Singleton1 {
        public static final Singleton1 INSTANCE;
        private String name;
        
        static {
            INSTANCE = new Singleton1();
            try {
                InputStream inputStream = Singleton1.class.getClassLoader().getResourceAsStream("singleton.properties");
                Properties properties = new Properties();
                properties.load(inputStream);
                String name = properties.getProperty("singleton1.name");
                INSTANCE.name = name;
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
        
        private Singleton1(){}
    
        public String getName() {
            return name;
        }
    }
    View Code

    四、懒汉式

    方式一:

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

    注:此方式有线程安全问题,只适用于单线程环境。

    方式二:同步代码块

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

    注:此方式虽然解决了线程安全问题,但是效率低,不推荐使用

    方式三:

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

     效率比前一种高,推荐使用

    方式四:静态内部类(强烈推荐使用)

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

    注:

    在内部类被加载和初始化时,才创建工 NSTANCE实例对象。

    静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。因为是在内部类加载和初始化时,创建的,因此是线程安全的。

  • 相关阅读:
    结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程--课程实验3
    深入理解系统调用 -- 课程实验2
    基于mykernel 2.0编写一个操作系统内核--课程实验1
    如何评测软件工程知识技能水平?
    如何评测一个软件工程师的计算机网络知识水平与网络编程技能水平?
    深入理解TCP协议及其源代码
    Socket与系统调用深度分析
    创新产品的需求分析:未来的图书是什么样的
    构建调试Linux内核网络代码的环境MenuOS系统
    php db2 返回当前insert记录的自增id
  • 原文地址:https://www.cnblogs.com/bear7/p/13403382.html
Copyright © 2020-2023  润新知