• java 单例模式5种写法


    学习整理

    饱汉模式(懒汉模式)

     1 // 饱汉
     2 // UnThreadSafe
     3 public class Singleton1 {
     4   private static Singleton1 singleton = null;
     5   private Singleton1() {
     6   }
     7   public static Singleton1 getInstance() {
     8     if (singleton == null) {
     9       singleton = new Singleton1();
    10     }
    11     return singleton;
    12   }
    13 }

    优点:懒加载启动快,资源占用小,使用时才实例化,无锁。

    缺点:非线程安全。

    饱汉模式(懒汉模式)--线程安全

     1 public class Singleton {
     2 
     3     /**
     4      * 定义一个变量来存储创建好的类实例
     5      */
     6 
     7     private static Singleton uniqueInstance = null;
     8 
     9     /**
    10      * 私有化构造方法,好在内部控制创建实例的数目
    11      */
    12 
    13     private Singleton(){
    14     }
    15 
    16     /**
    17      * 定义一个方法来为客户端提供类实例
    18      * @return 一个Singleton的实例
    19      */
    20 
    21     public static synchronized Singleton getInstance(){
    22 
    23         //判断存储实例的变量是否有值
    24         if(uniqueInstance == null){
    25             //如果没有,就创建一个类实例,并把值赋值给存储类实例的变量
    26             uniqueInstance = new Singleton();
    27         }
    28 
    29         //如果有值,那就直接使用
    30         return uniqueInstance;
    31     }
    32 
    33     /**
    34      * 示意方法,单例可以有自己的操作
    35      */
    36 
    37     public void singletonOperation(){
    38 
    39 //功能处理
    40 
    41     }
    42 
    43     /**
    44      * 示意属性,单例可以有自己的属性
    45      */
    46 
    47     private String singletonData;
    48 
    49     /**
    50      * 示意方法,让外部通过这些方法来访问属性的值
    51      * @return 属性的值
    52      */
    53 
    54     public String getSingletonData(){
    55 
    56         return singletonData;
    57 
    58     }
    59 
    60 }            

     优点:同上,但加锁了。

     缺点:synchronized 为独占排他锁,并发性能差。即使在创建成功以后,获取实例仍然是串行化操作。

    饱汉模式(懒汉模式)--双重加锁检查DCL(Double Check Lock)

     1 public class Singleton {
     2 
     3     /**
     4      * 对保存实例的变量添加volatile的修饰
     5      */
     6 
     7     private volatile static Singleton instance = null;
     8 
     9     private Singleton(){
    10 
    11     }
    12 
    13     public static Singleton getInstance(){
    14 
    15 //先检查实例是否存在,如果不存在才进入下面的同步块
    16 
    17         if(instance == null){
    18 
    19 //同步块,线程安全的创建实例
    20 
    21             synchronized(Singleton.class){
    22 
    23 //再次检查实例是否存在,如果不存在才真的创建实例
    24 
    25                 if(instance == null){
    26 
    27                     instance = new Singleton();
    28 
    29                 }
    30 
    31             }
    32 
    33         }
    34 
    35         return instance;
    36 
    37     }
    38 
    39 }

     优点:懒加载,线程安全。

     注:实例必须有 volatile 关键字修饰,其保证初始化完全。

    饿汉模式

     1 public class Singleton {
     2 
     3 //4:定义一个静态变量来存储创建好的类实例
     4 
     5 //直接在这里创建类实例,只会创建一次
     6 
     7     private static Singleton instance = new Singleton();
     8 
     9 //1:私有化构造方法,好在内部控制创建实例的数目
    10 
    11     private Singleton(){
    12 
    13     }
    14 
    15 //2:定义一个方法来为客户端提供类实例
    16 
    17 //3:这个方法需要定义成类方法,也就是要加static
    18 
    19 //这个方法里面就不需要控制代码了
    20 
    21     public static Singleton getInstance(){
    22 
    23 //5:直接使用已经创建好的实例
    24 
    25         return instance;
    26 
    27     }
    28 
    29 }

     优点:饿汉模式天生是线程安全的,使用时没有延迟。

     缺点:启动时即创建实例,启动慢,有可能造成资源浪费。

    Holder模式

     1 public class Singleton {
     2     /**
     3      * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
     4      * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
     5      */
     6     private static class SingletonHolder{
     7         /**
     8          * 静态初始化器,由JVM来保证线程安全
     9          */
    10         private static Singleton instance = new Singleton();
    11     }
    12     /**
    13      * 私有化构造方法
    14      */
    15     private Singleton(){
    16     }
    17     public static  Singleton getInstance(){
    18         return SingletonHolder.instance;
    19     }
    20 }

     优点:将懒加载和线程安全完美结合的一种方式(无锁)。(推荐)

    备注:

    1. 全局共享,独一份;

    2. 构造函数不暴露(如果暴露便不能保证一份),自己负责自己的构造;

    3. 懒汉式:Lazy load,用到才加载,非线程安全。如何保证线程安全呢:

    (1) synchronized getInstance()。

    (2)双重检查加锁(volatile)。

    4. 饿汉式:一开始就申请好,浪费了点资源,但其线程安全。

    5. Holder模式:

    (1)改成内部类,由JVM保证线程安全性。

  • 相关阅读:
    [原创]平面机器人的避障策略思考
    做个快乐的程序员
    [知识]双音多频(DTMF)信号
    osg 关于LOD
    (3)vtkMapper
    关于坐标系,关于矩阵及线性相关和无关的关系
    osg找不到插件的解决办法
    逆风飞扬,吴仁宏
    整合qt设计师和vs2008出了点问题,记下来
    关于NodeVisitor访问者模式
  • 原文地址:https://www.cnblogs.com/borter/p/9590273.html
Copyright © 2020-2023  润新知