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

    单例模式

    一、单例模式介绍

    单例模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

    二、单例设计模式的八种方式

    1)饿汉式(静态常量)

    2)饿汉式 (静态代码块)

    3)懒汉式(线程不安全)

    4)懒汉式(线程安全,同步方法)

    5)双重检查

    6)静态内部类

    7)枚举

    三、具体实现

    1. 饿汉式(静态常量)

    1)创建静态常量实例

    2)构造器私有化(防止new)

    3)向外暴露一个静态的公共方法。

    4)代码实现

    /**
     * 饿汉式(静态常量)
     */
    public class Singleton1 {
    
        // 1.创建静态常量实例
        private final static Singleton1 instance = new Singleton1();
    
        //2. 构造函数私有化
        private Singleton1(){
        }
    
        //3.获取实例对象
        public static Singleton1 getInstance(){
            return instance;
        }
    }
    

    优缺点说明

    1)优点:写法简单,在类装载的时候就完成了实例化。避免了线程同步问题。

    2)缺点:在类装载时就完成实例化,没有达到懒加载的效果。如果从始至终从未使用过这个实例,则会造成内存浪费。

    2. 饿汉式(静态代码块)

    1)静态代码块中,创建单例对象。

    2)构造函数私有化

    3)提供公有的静态方法,返回实例对象

    /**
     * 饿汉式(静态常量)
     */
    public class SingletonTest2 {
        public static void main(String[] args) {
            //测试
            Singleton instance1 = Singleton.getInstance();
            Singleton instance2 = Singleton.getInstance();
            System.out.println(instance1 == instance2); // true
            System.out.println("instance1.hashCode=" + instance1.hashCode());
            System.out.println("instance2.hashCode=" + instance2.hashCode());
        }
    }
    class Singleton{
        // 1.静态代码块中,创建单例对象
        private static Singleton instance;
        static{
            instance = new Singleton();
        }
    
        //2. 构造函数私有化
        private Singleton(){
        }
    
        //3.获取实例对象
        public static Singleton getInstance(){
            return instance;
        }
    }
    

    分析:

    1)和饿汉式(静态常量)是一样的,只不过将类实例化的过程放在了静态代码块中。

    3、懒汉式(线程不安全)

    思路:提供一个静态的公有方法,当使用该方法时,才去创建实例对象

    /**
     * 懒汉式(线程不安全)
     */
    public class SingletonTest3 {
        public static void main(String[] args) {
            //测试
            Singleton instance1 = Singleton.getInstance();
            Singleton instance2 = Singleton.getInstance();
            System.out.println(instance1 == instance2); // true
            System.out.println("instance1.hashCode=" + instance1.hashCode());
            System.out.println("instance2.hashCode=" + instance2.hashCode());
        }
    }
    
    class Singleton{
        private static Singleton instance;
    
        private Singleton(){
        }
    
        //3.获取实例对象
        public static Singleton getInstance(){
            if(instance==null){
                instance = new Singleton();
            }
           return instance;
        }
    }
    

    优缺点说明:

    1)起到了懒加载的效果,但只能在单线程下使用。

    2)如果在多线程下,一个线程进入了if(instance == null)语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时就会产生多个实例。

    3)结论:在实际开发中,不要使用这种方式

    4.懒汉式(线程安全,同步方法)

    /**
     * 懒汉式(线程安全,同步方法)
     */
    public class SingletonTest4 {
        public static void main(String[] args) {
            //测试
            Singleton instance1 = Singleton.getInstance();
            Singleton instance2 = Singleton.getInstance();
            System.out.println(instance1 == instance2); // true
            System.out.println("instance1.hashCode=" + instance1.hashCode());
            System.out.println("instance2.hashCode=" + instance2.hashCode());
        }
    }
    
    class Singleton{
        private static Singleton instance;
    
        private Singleton(){
        }
        //3.获取实例对象
        public static synchronized Singleton getInstance(){
            if(instance==null){
                instance = new Singleton();
            }
           return instance;
        }
    }
    

    优缺点分析:

    1)解决了线程安全问题。

    2)方法进行同步效率太低,每个线程想要获得实例时,必须等待其余线程执行完。

    3)结论:不推荐使用

    5. 双重检查

    /**
     * 双重检查
     */
    public class SingletonTest5 {
        public static void main(String[] args) {
            //测试
            Singleton instance1 = Singleton.getInstance();
            Singleton instance2 = Singleton.getInstance();
            System.out.println(instance1 == instance2); // true
            System.out.println("instance1.hashCode=" + instance1.hashCode());
            System.out.println("instance2.hashCode=" + instance2.hashCode());
        }
    }
    
    class Singleton{
        private static Singleton instance;
    
        private Singleton(){
        }
        //3.获取实例对象
        public static Singleton getInstance(){
            if(instance==null){
                synchronized(Singleton.class){
                    if(instance == null){
                        instance = new Singleton();
                    }
                }
            }
           return instance;
        }
    }
    

    优缺点分析:

    1)双重检查概念是多线程开发中经常使用到的,即保证线程安全,又避免反复进行方法同步。

    2)线程安全,符合懒加载,效率较高。

    3)推荐使用

    6. 静态内部类

    /**
     * 静态内部类
     */
    public class SingletonTest6 {
        public static void main(String[] args) {
            //测试
            Singleton instance1 = Singleton.getInstance();
            Singleton instance2 = Singleton.getInstance();
            System.out.println(instance1 == instance2); // true
            System.out.println("instance1.hashCode=" + instance1.hashCode());
            System.out.println("instance2.hashCode=" + instance2.hashCode());
        }
    }
    
    class Singleton{
        private Singleton(){
        }
        private static class SingletonInstance{
            public final static Singleton INSTANCE = new Singleton();
        }
    
        public static Singleton getInstance(){
            return SingletonInstance.INSTANCE;
        }
    }
    

    优缺点分析:

    1)采用了类装载机制保证初始化实例时只有一个线程。

    2)静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时调用getInstance方法才会装载SingletonInstance类,完成instance实例化。

    3)类的静态属性只会在第一次加载类时初始化。JVM帮我们保证了线程的安全性,在类初始化时,别的线程无法进入。

    4)推荐使用

    7. 枚举

    /**
     * 枚举
     */
    public class SingletonTest7 {
        public static void main(String[] args) {
            //测试
            Singleton instance1 = Singleton.INSTANCE;
            Singleton instance2 = Singleton.INSTANCE;
            System.out.println(instance1 == instance2); // true
            System.out.println("instance1.hashCode=" + instance1.hashCode());
            System.out.println("instance2.hashCode=" + instance2.hashCode());
        }
    }
    enum Singleton{
        INSTANCE;
    }
    

    优缺点说明:

    1)借助枚举实现单例模式。不进避免多线程同步问题,还能防止反序列化重新创建新的对象。

    2)推荐使用

    四、源码分析

    单例模式在JDK应用的源码分析

    1)jdk中,java.lang.Runtime就是经典的单例模式(饿汉式)

    2)代码分析

    五、单例模式注意事项和细节说明

    1)单例模式保证了系统内存中该类只存在一个对象,节省了系统资源。对于一些需要频繁创建销毁的对象,单例模式可以提高性能

    2)当想实例化一个单例类时,必须使用相应的获取对象的方法,而不是new

    3)单例模式使用场景:需要频繁创建和销毁的对象、创建对象耗时过多或资源耗费多(重量级对象)、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂)

  • 相关阅读:
    Objective-C入门教程03:属性(@property和@synthesize)
    iOS 开发的9个超有用小技巧
    oc关于非原子属性
    如果局部变量与实例变量同名,那么如何在局部变量的作用域内引用实例变量?
    从0开始搭建vue+webpack脚手架(一)
    ES6学习之 解构赋值
    Vue+webpack项目中实现跨域的http请求
    Vuejs核心思想学习笔记
    更改file文件上传默认CSS样式
    javascript获取style兼容性问题
  • 原文地址:https://www.cnblogs.com/chao-zjj/p/11273741.html
Copyright © 2011-2022 走看看