Java实现单例模式的五种方法介绍

作者:Knight_AL 时间:2022-10-20 17:32:56 

饿汉式

立即加载

防止new对象,构造私有,写一个公共的方法返回对象

占用空间,线程安全

public class Singleton {
   /**
    * 私有构造
    */
   private Singleton(){
       System.out.println("构造函数Singleton");
   }
   private static Singleton singleton = new Singleton();
   public static Singleton getInstance(){
       return singleton;
   }
}

懒汉式

延迟加载

占用空间小,效率有问题,线程不安全

public class Singleton {
   /**
    * 私有构造
    */
   private Singleton(){
       System.out.println("构造函数Singleton");
   }
   private static Singleton singleton = null;
   public static Singleton getInstance(){
       if (singleton == null){
           singleton = new Singleton();
       }
       return singleton;
   }
}

解决线程安全问题

在方法上加synchronized同步锁或是用同步代码块对类加同步锁,此种方式虽然解决了多个实例对象问题,但是该方式运行效率却很低下,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以继续运行。

锁太大

public class Singleton {
   /**
    * 私有构造
    */
   private Singleton(){
       System.out.println("构造函数Singleton");
   }
   private static Singleton singleton = null;
   public static synchronized Singleton getInstance(){
       if (singleton == null){
           singleton = new Singleton();
       }
       return singleton;
   }
}

双重检查锁

提高同步锁的效率

使用双重检查锁进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。

第一个if判断

第一个线程进来new了Singleton,那么singleton就有值,第二个线程进来,那么进行第一个if判断,不为null,直接返回,不用再去new了,提升了效率

第二个if判断

两个线程同时进来,在synchronized,第一个线程进入,另一个线程等待,第一个线程new Singleton,然后返回,另一个线程发现了第一个线程走了,进入synchronized,如果不进行if判断,那么还会new Singleton,导致线程不安全

public class Singleton {
   /**
    * 私有构造
    */
   private Singleton(){
       System.out.println("构造函数Singleton");
   }
   private static Singleton singleton = null;
   public static synchronized Singleton getInstance(){
       if (singleton == null){  //这个检查是提高效率的
           synchronized (Singleton.class){
               if (singleton == null){
                   singleton = new Singleton();   //这个检查是防止线程安全的
               }
           }
       }
       return singleton;
   }
}

静态内部类

这种方式引入了一个内部静态类(static class),静态内部类只有在调用时才会加载,它保证了Singleton 实例的延迟初始化,又保证了实例的唯一性。它把singleton 的实例化操作放到一个静态内部类中,在第一次调用getInstance() 方法时,JVM才会去加载InnerObject类,同时初始化singleton 实例,所以能让getInstance() 方法线程安全。

特点是:即能延迟加载,也能保证线程安全。

静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。

public class Singleton {
   /**
    * 私有构造
    */
   private Singleton(){
   }
   private static class InnerObject{
       private static Singleton singleton = new Singleton();
   }
   public static synchronized Singleton getInstance(){
       return InnerObject.singleton;
   }
}

内部枚举类实现

防止反射和反序列化攻击

实上,通过Java反射机制是能够实例化构造方法为private的类的。这也就是我们现在需要引入的枚举单例模式。

public class SingletonFactory {
   /**
    * 私有构造
    */
   private enum EnumSingleton{
       SINGLETON;
       private Singleton6 singleton;
       //枚举类的构造方法在类加载是被实例化
       private EnumSingleton(){
           singleton = new Singleton6();
       }
       public Singleton6 getInstance(){
           return singleton;
       }
   }
   public static Singleton6 getInstance(){
       return EnumSingleton.SINGLETON.getInstance();
   }
}
class Singleton6{
   public Singleton6(){
   }
}

来源:https://donglin.blog.csdn.net/article/details/128773676

标签:Java,单例模式
0
投稿

猜你喜欢

  • 解决IDEA和CMD中java命令提示错误: 找不到或无法加载主类的问题

    2023-09-19 02:31:16
  • 使用Java和ffmpeg把音频和视频合成视频的操作方法

    2022-08-22 07:30:20
  • java实现简单控制台通讯录

    2023-05-24 14:33:20
  • 关于@ConditionalOnProperty的作用及用法说明

    2023-11-24 02:39:19
  • Android中切换到主线程执行的方法

    2023-08-19 07:02:28
  • android实现简单的画画板实例代码

    2023-02-21 05:46:02
  • Java Scala实现数据库增删查改操作详解

    2022-02-03 05:09:22
  • Java堆&优先级队列示例讲解(上)

    2023-04-09 11:09:59
  • 再议C#中的装箱与拆箱的问题详解

    2022-09-30 03:45:40
  • 解决springboot遇到autowire注入为null的问题

    2022-04-15 02:37:59
  • 浅谈virtual、abstract方法和静态方法、静态变量理解

    2022-08-29 02:29:14
  • Android之ListView分页加载数据功能实现代码

    2023-08-13 03:44:17
  • Java关键字volatile详析

    2023-01-21 21:51:11
  • C#实现时间戳与标准时间的互转

    2023-07-16 08:09:38
  • Unity 如何通过反射给gameObject添加组件

    2022-06-14 20:58:34
  • 通过springboot+mybatis+druid配置动态数据源

    2023-06-20 16:48:30
  • OPENCV+JAVA实现人脸识别

    2022-03-15 18:31:39
  • Android开发之拖动条和评分组件用法分析

    2022-01-15 02:55:18
  • Java中的synchronized 优化方法之锁膨胀机制

    2023-10-02 03:44:15
  • Java Synchronized锁的使用详解

    2022-10-11 12:59:33
  • asp之家 软件编程 m.aspxhome.com