博客
关于我
单例模式的几种实现
阅读量:453 次
发布时间:2019-03-06

本文共 2061 字,大约阅读时间需要 6 分钟。

  简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来也很容易,直接看demo吧

 懒汉式写法(线程不安全)

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

按照我的习惯,我恨不得写满注释,怕你们看不懂,但是这个代码实在太简单了,所以我没写任何注释,如果这几行代码你都看不明白的话,那你可以洗洗睡了,等你睡醒了再来看我的博客说不定能看懂。

上面的是最基本的写法,也叫懒汉写法(线程不安全)下面我再公布几种单例模式的写法:

 

懒汉式写法(线程安全)

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 Singleton instance = new Singleton();     private Singleton (){}     public static Singleton getInstance() {       return instance;     }  }

静态内部类

public class Singleton {     private static class SingletonHolder {       private static final Singleton INSTANCE = new Singleton();     }     private Singleton (){}     public static final Singleton getInstance() {       return SingletonHolder.INSTANCE;     }  }
只有第一次调用getInstance方法时,虚拟机才加载 SingletonHolder并初始化INSTANCE,只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。目前此方式是所有单例模式中最推荐的模式,但具体还是根据项目选择。

 枚举

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

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏。

双重校验锁

public class Singleton {     private volatile static Singleton singleton;     private Singleton (){}     public static Singleton getSingleton() {     if (singleton == null) {         synchronized (Singleton.class) {         if (singleton == null) {             singleton = new Singleton();         }         }     }     return singleton;     }  }

线程安全,延迟初始化。这种方式采用双锁机制,安全且在多线程情况下能保持高性能

总结:我个人比较喜欢静态内部类写法和饿汉式写法,其实这两种写法能够应付绝大多数情况了。其他写法也可以选择,主要还是看业务需求吧。

转载地址:http://xsdbz.baihongyu.com/

你可能感兴趣的文章
LeetCode50/Pow(x,n)
查看>>
Spring源码深度解析之事务
查看>>
Ubuntu 20.04 Docker 安装并配置
查看>>
Cassandra查询操作趟坑记录
查看>>
.NET面试题解析(02)-拆箱与装箱
查看>>
使用c#对MongoDB进行查询(1)
查看>>
Linux常用命令
查看>>
SpringBoot第十七篇:定时任务
查看>>
SpringBoot第二十三篇:安全性之Spring Security
查看>>
科技周刊第五期:科学技术在发展中的作用
查看>>
科技周刊第十期:自顶向下还是自底向上?
查看>>
mysql查询含有指定字段的所有表
查看>>
如何理解java反射?
查看>>
获取任务的执行结果
查看>>
基于跳跃表的 ConcurrentSkipListMap 内部实现(Java 8)
查看>>
虚拟机字节码执行引擎
查看>>
Java 字符流文件读写
查看>>
Python数据分析(二): Numpy技巧 (2/4)
查看>>
Python数据分析(二): Pandas技巧 (2)
查看>>
学习Identity Server 4的预备知识 (误删, 重补)
查看>>