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来调用私有构造方法。

  • 相关阅读:
    【Anagrams】 cpp
    【Count and Say】cpp
    【Roman To Integer】cpp
    【Integer To Roman】cpp
    【Valid Number】cpp
    重构之 实体与引用 逻辑实体 逻辑存在的形式 可引用逻辑实体 不可引用逻辑实体 散弹式修改
    Maven项目聚合 jar包锁定 依赖传递 私服
    Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
    mysql案例~tcpdump的使用
    tidb架构~本地化安装
  • 原文地址:https://www.cnblogs.com/13jhzeng/p/5256424.html
Copyright © 2011-2022 走看看