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

    一、什么是单例模式:

    单例模式是一种确保了一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。被实例化的类称为单例类。

    二、单例模式的特点:

    1. 单例类只有一个实例。
    2. 单例类必须自行创建自己唯一的实例。
    3. 单例类必须给其他对象提供这个实例。

    注意:虽然单例模式和单例类限定了只能有一个实例,但是作为单例模式的推广,可以推广到任意且有限多个实例的情况,这时候被称为多例模式和多例类。

    三、单例模式的结构:

    1. 一个单例类只有一个实例。
    2. 单例类的实例持有对自己的引用。

    四、单例模式的实例化:

    Java中单例模式有着自己的特点,具体表现在单例类的实例化上:

    饿汉式单例类(静态常量)

     1 /**
     2  * 饿汉式(静态常量)
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/4 22:12:28
     6  */
     7 public class HungerSingleton {
     8     private static final HungerSingleton SINGLETON= new HungerSingleton();
     9 
    10     /**
    11      * 私有的默认构造函数
    12      */
    13     private HungerSingleton() {
    14     }
    15 
    16     /**
    17      * 静态工厂方法
    18      */
    19     public static HungerSingleton getInstance() {
    20         return SINGLETON;
    21     }
    22 }

    Java中最简单的单例类,类的单例被声明为静态变量,在类加载时,调用类的私有构造函数,静态变量被实例化。

    特点:

      1.类的构造函数私有,避免了外界利用构造函数创建任意多的实例。

      2.且由于构造函数私有,类不能被继承。

      3.只能通过静态方法getInstance()来获取类的实例对象。

    优点:

      类装载的时候就完成实例化。避免了线程同步问题。

    缺点:

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

      饿汉式单例类(静态代码块):

     1 /**
     2  * 饿汉式单例类(静态代码块)
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/13 22:45:24
     6  */
     7 public class HungerSington_StaticCode {
     8     private static HungerSington_StaticCode singleton;
     9 
    10     /**
    11      * 静态代码块
    12      */
    13     static {
    14         singleton= new HungerSington_StaticCode();
    15     }
    16 
    17     /**
    18      * 私有构造函数
    19      */
    20     private HungerSington_StaticCode() {
    21     }
    22 
    23     /**
    24      * 获取单例类实例的唯一接口
    25      *
    26      * @return 单例类
    27      */
    28     public static HungerSington_StaticCode getInstance() {
    29         return singleton;
    30     }
    31 }

      特点:

      将单例类放在静态代码块中,也是类在加载时执行静态代码块中的代码,完成类的实例化,优缺点同静态常量。

    汉懒式单例类(线程不安全):

     1 /**
     2  * 懒汉式(线程不安全)[不可用]
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/13 22:52:24
     6  */
     7 public class LazySingleton_ThreadUnsafe {
     8     private static LazySingleton_ThreadUnsafe singleton;
     9 
    10     /**
    11      * 获取单例类实例
    12      *
    13      * @return 单例类实例
    14      */
    15     public static LazySingleton_ThreadUnsafe getInstance() {
    16         if (null == singleton) {
    17             singleton = new LazySingleton_ThreadUnsafe();
    18         }
    19 
    20         return singleton;
    21     }
    22 }

      特点:

      1.达到了延迟加载的目的,只有在单例类第一次被引用时将自己实例化。

      2.在单线程下使用。

      缺点:  

      在多线程的环境中,多个线程同时进入if (null == singleton) {},还未执行singleton = new LazySingleton_ThreadUnsafe()时,另一个线程也恰好进入这里,就会造成单例类多个实例,线程不安全,不可以再多线程的环境下使用。

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

     1 /**
     2  * 懒汉式(线程安全,同步方法)
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/4 22:23:02
     6  */
     7 public class LazySingleton {
     8     private static LazySingleton lazySingleton = null;
     9 
    10     /**
    11      * 构造函数
    12      */
    13     private LazySingleton() {
    14     }
    15 
    16     /**
    17      * 静态工厂方法,返回懒汉式实力类的唯一实例
    18      *
    19      * @return
    20      */
    21     public static synchronized LazySingleton getInstance() {
    22         if (lazySingleton == null) {
    23             return lazySingleton = new LazySingleton();
    24         }
    25         return lazySingleton;
    26     }
    27 }

      特点:

      使用了synchronized对静态工厂类方法进行了同步,安全处理多线程的问题。

      缺点:

      每个线程执行getInstance()方法都要进行同步,大大降低了执行的效率。且getInstance()只需要实例化一次就可以。

      懒汉式(线程不安全,同步代码块)

     1 /**
     2  * 懒汉式(线程安全,同步代码块)
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/13 23:12:08
     6  */
     7 public class LaSingleton_ThreadUnsafe {
     8     private static LaSingleton_ThreadUnsafe singleton;
     9 
    10     /**
    11      * 静态构造方法
    12      */
    13     private LaSingleton_ThreadUnsafe() {
    14     }
    15 
    16     /**
    17      * 获取单例类实例
    18      *
    19      * @return 单例类实例
    20      */
    21     public static LaSingleton_ThreadUnsafe getInstance() {
    22         if (null == singleton) {
    23             synchronized (LaSingleton_ThreadUnsafe.class) {
    24                 singleton = new LaSingleton_ThreadUnsafe();
    25             }
    26         }
    27         return singleton;
    28     }
    29 }

      特点:

      同步产生实例的代码块。

      缺点:

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

      懒汉式(双重检查):

     1 /**
     2  * 懒汉式(双重检查):
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/13 23:24:27
     6  */
     7 public class LazySingleton_DoubleCheck {
     8     private static volatile LazySingleton_DoubleCheck singleton;
     9 
    10     /**
    11      * 静态构造方法
    12      */
    13     private LazySingleton_DoubleCheck() {
    14     }
    15 
    16     /**
    17      * 获取单例类实例
    18      *
    19      * @return 单例类实例
    20      */
    21     public static LazySingleton_DoubleCheck getInstance() {
    22         if (null == singleton) {
    23             synchronized (LazySingleton_DoubleCheck.class) {
    24                 singleton = new LazySingleton_DoubleCheck();
    25             }
    26         }
    27         return singleton;
    28     }
    29 }

      特点:

      1.进行了两次if (singleton == null)检查,保证了线程安全。

      2.实例化代码只执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。

      优点:

      程安全;延迟加载;效率较高。

      静态内部类:

     1 /**
     2  * 静态内部类
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/13 23:28:58
     6  */
     7 public class Singleton_StaticInnerClass {
     8     /**
     9      * 私有构造方法
    10      */
    11     private Singleton_StaticInnerClass() {
    12     }
    13 
    14     /**
    15      * 静态内部类
    16      */
    17     private static class SingletonInstance {
    18         private static final Singleton_StaticInnerClass SINGLETON = new Singleton_StaticInnerClass();
    19     }
    20 
    21     /**
    22      * 获取单例类实例
    23      *
    24      * @return 单例类实例
    25      */
    26     private static Singleton_StaticInnerClass getInstance() {
    27         return SingletonInstance.SINGLETON;
    28     }
    29 }

      特点:

      类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

      优点:

      避免了线程不安全,延迟加载,效率高。

      枚举:

     1 /**
     2  * 枚举
     3  *
     4  * @author ZhouDX
     5  * @since 2019/3/13 23:33:43
     6  */
     7 public enum Singleton_Enum {
     8     SINGLETON;
     9 
    10     public void whateverMethod() {
    11     }
    12 }

      特点:

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

      优点:

      当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。

    懒汉式单例类与饿汉式单例类的比较:

    1. 饿汉式单例类在自己被加载时将自己实例化,即便加载器是静态的,依旧在加载时实例化自己;懒汉式单例类在第一次被引用时将自己实例化,如果加载器是静态的,懒汉式单例类被加载时不会将自己实例化。
    2. 从资源利用角度讲,懒汉式单例类的资源利用效率高点;从速度和反应时间来讲,饿汉式的好点。
  • 相关阅读:
    vue的特点 关键字
    小程序技术实现
    SpringCloud简历模板
    SpringBoot简历模板
    SpringCloud+Eureka快速搭建微服架构
    Docker 面试题
    说说mysql的存储引擎,有什么区别?索引的介绍
    mysql语句
    fail-fast 与 fail-save 机制的区别
    动态规划总结
  • 原文地址:https://www.cnblogs.com/zhoudaxing/p/10473847.html
Copyright © 2011-2022 走看看