精华内容
下载资源
问答
  • 1.单例设计模式 单例设计模式简介 单例设计模式中,单例对象的类必须保证在jvm中只存在一个实例. 应用:Spring中的Bean默认都是单例的.线程池,缓存,日志对象等一般设计成单例的. 实现单例模式的思路为:先私有化构造...

    设计模式

    1.单例设计模式

    单例设计模式简介

    单例设计模式中,单例对象的类必须保证在jvm中只存在一个实例.

    应用:Spring中的Bean默认都是单例的.线程池,缓存,日志对象等一般设计成单例的.

    实现单例模式的思路为:先私有化构造方法;创建本类对象并提供公共的方法方式;

    1.1经典的懒汉模式

    所谓懒汉模式,是指需要单例对象的时候,才创建类的实例.这种方式在多线程下可能会创建多个对象,是线程不安全的.多线程下可能导致单例模式失效.

    package com.begank.revival.juc.singleton;
    
    /**
     * @ClassName :经典的懒汉式单例模式
     * @Author : begank
     */
    public class LazySingleton {
        //懒汉对象引用
        private static LazySingleton INSTANCE;
    
        //私有化构造方法
        private LazySingleton(){}
    
        //提供公共的访问方式
        public static LazySingleton getInstance(){
            //多线程下,懒汉式是不安全的,因为有可能同时有多条线程进入下面的判断,导致创建多个对象
            if (INSTANCE == null){
                INSTANCE = new LazySingleton();
            }
            return INSTANCE;
        }
    }
    
    1.2经典的饿汉式

    所谓饿汉式,是指类一加载,类对象就创建了.饿汉式是"天然"的线程安全的,因为饿汉式利用类加载只会加载一次这个特性(这是Java虚拟机提供的).

    饿汉式有可能会造成资源的浪费,即创建了对象但并没有使用.但是我觉得这个可以忽略,因为不太可能出现触发加载这个类,但不使用这个对象的情况.

    package com.begank.revival.juc.singleton;
    
    /**
     * @ClassName :饿汉式单例模式
     * @Author : begank
     */
    public class HungrySingleton {
    
        //在类加载的时候,就创建类对象.由于类只会加载一次,所以保证其是线程安全的
        private static HungrySingleton INSTANCE = new HungrySingleton();
    
        private HungrySingleton(){}
    
        public static HungrySingleton getInstance(){
            return INSTANCE;
        }
    }
    
    1.3双重锁校验懒汉式-DCL

    双重锁校验模式是一种比较优雅的单例实现,既可以保证有需要才创建对象,又可以保证只创建一个对象.其中:

    1. 实例对象加volatile关键字,是因为volatile关键字可以禁止指令重排,指令重排优化可能导致instance对象还没有创建,就已经赋值给了Instance引用,从而其他线程获得一个null对象.
    2. 所谓指令重排,是指CPU不按照程序指定的顺序执行指令,但会保证执行结果的准确性.比如代码写的是A xx ; B xx; C= Axx;CPU在实际执行时,有可能先执行C语句再执行A语句,因为他们没有先后依赖关系.也不会改变程序结果.
    3. 锁不加在方法上,避免每次获取实例都需要加锁,加锁是一个很耗性能的过程.
    4. 在创建对象前再一次判断对象是否为空,避免两个线程同时排队获取锁对象时,第二个线程再次创建对象.
    package com.begank.revival.juc.singleton;
    
    /**
     * @ClassName :双重锁校验懒汉式单例
     * @Author : begank
     */
    public class DoubleCheckSingleton {
    
        /**
         * 加volatile关键字,可以禁止指令重排.
         * 指令重排优化可能导致instance对象还没有创建,就已经赋值给了Instance引用,从而其他线程获得一个null对象.
         */
        private static volatile DoubleCheckSingleton INSTANCE;
    
        private DoubleCheckSingleton(){}
    
        /**
         * 双重锁校验机制;
         * 锁不加在方法上,避免每次获取实例都需要加锁,加锁是一个很耗性能的过程
         */
        public static DoubleCheckSingleton getInstance(){
            //第一次判断,如果对象还未创建,则获取锁对象.
            if (INSTANCE == null){
                synchronized (DoubleCheckSingleton.class){
                    //第二次判断,有可能两个线程同时进入第一层判断,即此时对象未创建.
                    //此时,两个线程依次排队希望获取锁对象.所以在实际创建对象前,还需要再判空.
                    if (INSTANCE == null){
                        INSTANCE = new DoubleCheckSingleton();
                    }
                }
            }
    
            return INSTANCE;
        }
    }
    
    1.4静态内部类模式单例

    内部类模式单例,通过在单例对象中创建内部类的形式,在静态内部类中创建单例对象,由单例类提供公共访问方式供外部获取.

    package com.begank.revival.juc.singleton;
    
    /**
     * @ClassName :内部类单例模式
     * @Author : begank
     */
    public class InnerSingleton {
        
        private InnerSingleton(){}
    
        public static InnerSingleton getInstance(){
            return Holder.INSTANCE;
        }
    
        private static class Holder{
            static InnerSingleton INSTANCE = new InnerSingleton();
        }
    }
    
    1.5枚举实现单例

    以上的所有方法,在反射和反序列化时,都有可能失效.Java反射是可以创建构造方法为private的类的.

    使用枚举可以优雅的实现单例模式.

    package com.begank.revival.juc.singleton;
    
    /**
     * @ClassName :枚举模式单例
     * @Author : begank
     */
    public enum EnumSingleton {
        /**
         * 单例对象
         */
        INSTANCE;
        
        public EnumSingleton getInstance(){
            return INSTANCE;
        }
    }
    
    展开全文
  • 一、什么是单例设计模式 在写单例设计模式前,首先需要了解什么是单例设计模式:单例模式,指的是一个类只有一个实例,并且有一个全局可以访问的接口。他有以 下个优点: (1)可以节省内存和计算,很多时候我们...

    一、什么是单例设计模式

    	在写单例设计模式前,首先需要了解什么是单例设计模式:单例模式,指的是一个类只有一个实例,并且有一个全局可以访问的接口。他有以
    下几个优点:
    	(1)可以节省内存和计算,很多时候我们其实只需要一个实例就够了,多个实例会造成浪费,比如对于一些初始化比较耗时的类,就只用生成
    一个实例保存在内存中供大家一起实用,没有必要多次生成新的实例。
    	(2)单例设计模式可以保证全局计算结果的正确,比如一个全局计数器用于统计人数,如果有多个计数器反而会造成混乱。
    	(3)方便管理,对于很多工具类,我们生成一个实例,然后通过一个统一的入口来获取这个单例,太多实例反而会眼花缭乱。
    

    二、单例设计模式适用场景

    1. 无状态的工具类,如日志工具类,我们不需要他来帮我们存储,只需要他来记录日志信息,这时候只需要一个实例就可以了。
    2. 全局信息类,如环境变量类,比如统计一个网站的浏览量,可以让这个类变成一个单例,在需要计数的时候拿出来用就可以了。

    三、常见的单例模式写法

    1. 饿汉式

    public class SingletonEH {
    
        private static SingletonEH singletonEH = new SingletonEH();
        
        private SingletonEH(){};
        
        public static SingletonEH getInstance(){
            return singletonEH;
        }
    }
    

    特点:在类装载的时候完成实例化,避免了线程同步问题
    缺点:如果从始至终没有使用到该实例,会造成内存浪费

    2. 懒汉式

    线程不安全的写法

    public class SingletonLH {
    
        private static SingletonLH singletonLH;
    
        private SingletonLH(){}
    
        public static SingletonLH getInstance(){
            if (singletonLH == null){
                singletonLH = new SingletonLH();
            }
            return singletonLH;
        }
    }
    

    特点:起到了懒加载的作用,在调用getInstance()方法后才去实例化对象。
    缺点:只能在单线程下使用。多线程情况下,如果一个线程进入了if (singletonLH == null)判断,还没有实例化的时候,另一个线程也进入了判断语句,这时候就会多次创建实例。

    线程安全的写法

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

    缺点:效率太低,为了让懒汉式线程安全且效率高,提出了双重检查式

    3. 双重检查式

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

    特点:线程安全,效率高
    缺点:无法防止被反序列化生成多个实例

    两个判断如果去掉第一个,会导致所有线程串行执行,效率低下。如果去掉第二个,可能会出现多个线程同时进入判断,从而产生多个实例。并没有保证线程安全,因此两个判断缺一不可。

    需要注意的地方是volatile来修饰了变量。它能有效防止重排序的发生,保证持有同一个对象锁的两个同步块只能串行执行,这样可以避免可能存在的一种情况:线程一先指向单例对象的内存地址(此时对象已经不是null了),但是还未初始化,这时候线程二进来了,且通过了是否为null的判断,将还未初始化的对象返回使用。这种情况会报错

    4. 静态内部类式

    public class SingletonStatic {
    
        private SingletonStatic(){}
    
        private static class SingletonStaticInstance{
            private static final SingletonStatic singletonStatic = new SingletonStatic();
        }
    
        public static SingletonStatic getInstance(){
            return SingletonStaticInstance.singletonStatic;
        }
    
    }
    

    特点:跟饿汉式类似,采用类装载的时候实例化对象,区别在于饿汉式是在类加载的时候实例化,静态内部类式是在调用了getInstance()方法的时候才会去完成对该实例的实例化,和双重检查式一样,线程安全且效率高
    缺点:无法防止被反序列化生成多个实例

    5. 枚举式(推荐)

    public enum SingletonEnum {
        INSTANCE;
        public void whateverMethod(){
            
        }
    }
    

    优点:简洁,线程安全,能防止序列化和反射创建多个实例从而破坏单例。

    展开全文
  • Java中单例模式是一种常见的设计模式单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类只能有一个实例。  2、单例类必须自己创建自己的...
      
    Java
    中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。
    
      单例模式有以下特点:
       1、单例类只能有一个实例。
      2、单例类必须自己创建自己的唯一实例。
      3、单例类必须给所有其他对象提供这一实例。

        单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

    一、懒汉式

        1.线程不安全  

    1. public class Singleton {  
    2.     private Singleton() {}  
    3.     private static Singleton single;   
    4.     public static Singleton getInstance() {  
    5.          if (single == null) {    
    6.              single = new Singleton();  
    7.          }    
    8.         return single;  
    9.     }  
    10. }  
        

        2.线程安全  

    1. public class Singleton {  
    2.     private Singleton() {}  
    3.     private static Singleton single;   
    4.     public static synchronized Singleton getInstance() {  
    5.          if (single == null) {    
    6.              single = new Singleton();  
    7.          }    
    8.         return single;  
    9.     }  
    10. }  

        3.双重检查锁定   

    1. public class Singleton {  
    2.     private Singleton() {}  
    3.     private volatile static Singleton single;   
    4.     public static Singleton getInstance() {  
    5.          if (single == null) { 
    6.             synchronized(Singleton.class){
    7.                  if(single==null){
    8.                     single = new Singleton();  
    9.                  }
    10.             }                
    11.          }    
    12.         return single;  
    13.     }  
    14. }  
         

         4.静态内部类  

    1. public class Singleton {  
    2.     private Singleton() {} 
    3.     private static class SingletonHolder{
    4.          private static final Singleton INSTANCE = new Singleton();  
    5.     }   
    6.     public static final Singleton getInstance() {  
    7.         return SingletonHolder.INSTANCE;  
    8.     }  
    9. }  

        这种方式利用classLoader的机制来保证初始化instance时只有一个县城。Singleton类虽然被撞在了,但instance不一定被初始化,因为SingletonHolder没有被主动使用,只有显示调用getInstance方法时,才会显示装在SingletonHolder类,从而实例化instance。

    二、饿汉式

    1. public class Singleton {  
    2.     private Singleton() {}  
    3.     private static Singleton single=new Singleton();   
    4.     public static Singleton getInstance() {  
    5.         return single;  
    6.     }  
    7. }  

       

       饿汉式与懒汉式的区别:

       1.概念

            饿汉式:类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。

            懒汉式:只有当调用getInstance的时候,才回去初始化这个单例。

       2.线程安全

            饿汉式:天生就是线程安全的,基于classloader机制避免了多线程的同步问题

            懒汉式:本身是非线程安全的,为了实现线程安全有几种写法。

          3.资源加载和性能

            饿汉式:在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速                             度也会更快,因为其资源已经初始化完成。

            懒汉式:会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延                             迟,之后就和饿汉式一样了。

    展开全文
  • 一、静态变量初始化实现线程安全的单例模式 static变量instance是在类被加载时初始化并仅被初始化一次,这样就可以保证只有一个instance被初始化。 public class Singleton { private static Singleton ...

    一、静态变量初始化实现线程安全的单例模式

    static变量instance是在类被加载时初始化并仅被初始化一次,这样就可以保证只有一个instance被初始化。

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

    二、经典的非线程安全单例模式实现类

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

    三、线程安全的单例模式实现类

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

    四、高效的线程安全的单例模式实现类

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

    写在最后:

    以上是我工作中常遇到的单例模式实现方式,欢迎补充…

    展开全文
  • 最简单的设计模式单例可以说是GOF23中最简单的一种设计模式,也经常用到。比如window的任务管理器,比如servlet对象等等。单例要完成的就是确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个唯一的实例...
  • Java 单例设计模式 常见4

    千次阅读 2019-10-06 19:49:52
    Java 单例设计模式 常见4适合功能场景主要特点饿汉式单例 Eager loading(立即加载方式)懒汉式单例 Lazy Loading(延迟加载方式)枚举单例ConcurrentHashMap容器单例 适合功能场景 配置文件读写对象, 数据库连接池, ...
  • 但是除了这两种方式,本文还会介绍其他几种实现单例的方式,让我们来一起看看吧。   简介 单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。 许多时候整个系统只需要拥有一个的...
  • 单例设计模式

    2021-03-17 20:05:40
    单例设计模式1、单例设计模式介绍2、几种实现单例的方式1、懒汉式,线程不安全2、懒汉式,线程安全3、饿汉式,线程安全5、登记式/静态内部类6、枚举3、应用场景 1、单例设计模式介绍 单例模式(Singleton Pattern)...
  • JAVA设计模式单例模式

    万次阅读 多人点赞 2014-04-16 06:51:34
     java中单例模式是一种常见的设计模式单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类只能有一个实例。  2、单例类必须自己创建自己的...
  • 饿汉式单例设计 懒汉式单例设计
  • 无论什么开发中,设计模式都起着关键的作用,其中比较常用的当属单例了~那么什么是单例设计模式呢? 1. 什么是单例设计模式(SINGLETON) 单例模式指的是在应用整个生命周期内只能存在一个实例。单例模式是一被...
  • 无论什么开发中,设计模式都起着关键的作用,其中比较常用的当属单例了~那么什么是单例设计模式呢? 1.什么是单例设计模式(SINGLETON) 单例模式指的是在应用整个生命周期内只能存在一个实例。单例模式是一被...
  • 绪论 设计模式分为三类型,共 23 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂...所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该
  • 创建型模式主要有简单工厂模式(并不是23种设计模式之一)、工厂方法、抽象工厂模式、单例模式、生成器模式和原型模式。 1.2. 结构型 用于帮助将多个对象组织成更大的结构。结构型模式主要有适配器模式adapter、...
  • 本文主要对几种单例写法的整理,并分析其优缺点。很多都是一些老生常谈的问题,但如果你不知道如何创建一个线程安全的单例,不知道什么是双检锁,那这篇文章可能会帮助到你。 饿汉式,线程安全 当被问到要实现一个...
  • 下面介绍一下几种实现单例设计模式的写法3.1 懒汉,线程不安全3.2 饿汉3.3 静态内部类3.4 枚举3.5 双重校验锁(jdk1.5)4.总结 1.单例设计模式 1.1 单例设计模式的定义: 保证一个类仅有一个实例,并提供...
  • 单例设计模式、工厂设计模式(简单工厂、方法工厂、抽象工厂)、代理设计模式(静态代理、动态代理(JDK原生代码实现、cglib实现))、适配器设计模式、模板设计模式、装饰者设计模式。 一、单例 设计模式 如果要求...
  • 除了常见的两,还有别的实现单例模式的方法吗? 1、单例模式的概念(个人总结非官方):  单例顾名思义就是程序运行中,最多只能有一个实例化的对象。(至于为什么这里不做介绍) 2、懒汉式、饿汉式的区别:...
  • 23种设计模式 - 单例设计模式单例模式算是Java设计模式中最简单的一种了,有好几种写法,这里主要介绍2种,分别是懒汉式和饿汉式。/** * 单例模式之饿汉式 */ public class Single { //1.私有的静态成员变量 ...
  • java单例设计模式

    2017-09-03 09:59:24
    学习java单例设计模式,看了篇比较好的文章和部分书籍资料,在此做一个总结供交流学习 一、单例设计模式的作用  单例设计模式可以保证某个类的对象只有一个且所有人使用的是同一个对象(下面会用代码来验证...
  • 二十三种设计模式(第1种)----几种问题较少的单例设计模式写法 单例设计模式之饿汉式 分析: 饿汉式顾名思义比较饥饿 创建类是将对象创建出来了。在多线程条件下可以保证单例。缺点:有点浪费内存空间,问题不大。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 81,760
精华内容 32,704
关键字:

单例设计模式一共几种