zoukankan      html  css  js  c++  java
  • 单例模式(Singleton Pattern)

    单例模式:确保一个类只有一个实例,并提供一个全局访问点。

    为什么需要单例模式?

    有一些对象只需要一个,比如:线程池,对话框,注册表的对象,日志对象,打印机、显卡等设备的驱动程序对象。如果这些类有多个实例,会导致许多问题的产生。

    1.第一种方式

    是否延迟初始化:是

    是否多线程安全:否

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

    这种方法只适合在单线程环境下。

    2.第二种方式:

    是否延迟初始化:是

    是否多线程安全:是

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

    这种方法采用synchronized关键字,迫使每个线程进入getInstance()方法之前,要等别的线程离开该方法,也就是不会有两个线程同时进入该方法。

    缺点是:同步会降低性能,而且只有第一次执行此方法时,才很真正需要同步,一旦单例类被实例化后,之后每次调用,都不需要同步了。

    3.第三种方式:

    是否延迟初始化:否

    是否多线程安全:是

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

    当类被加载时,马上实例化Singleton对象。

    缺点是,如果程序整个运行过程没有使用过Singleton对象,会导致浪费资源,因为该对象一直占用内存。

    第四种方式:

    是否延迟初始化:是

    是否多线程安全:是

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

    这种方法利用双重检查加锁,能减少getInstance()同步,首先检查实例是否已经创建,如果未创建,进行同步,否则直接返回已经存在的实例。

    第五种方式:

    是否延迟初始化:是

    是否多线程安全:是

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

    这种方式在Singleton类里面写了个内部类,实现当Singleton类被加载时,不会实例化Singleton对象,而是调用了Singleton.getInstance()时,将SingletonInner类加载时,Singleton才会实例化。相比第三种方法更加合理。

    第六种方法:

    是否延迟初始化:否

    是否多线程安全:是

    public enum Singleton {
        INSTANCE;
        private Singleton() {
        }
    }

    自JDK1.5起才能使用,更加简洁,自动支持序列化机制,绝对防止多次实例化,不能通过reflection attack来调用私有构造方法。

  • 相关阅读:
    16-镜像命名的最佳实践
    15-RUN vs CMD vs ENTRYPOINT
    14-Dockerfile常用指令
    13-调试Dockerfile
    12-镜像的缓存特性
    11-Dockerfile构建镜像
    10-构建镜像
    09-镜像的分层结构
    08-base镜像
    07-镜像-最小的镜像
  • 原文地址:https://www.cnblogs.com/13jhzeng/p/5256424.html
Copyright © 2011-2022 走看看