2019-09-30

定义
单例是一种设计模式,单例模式可以保证系统中只有一个类只有一个实例,而且该实例易于外界访问,从而方便实例个数的控制并节约系统资源。

单例模式通用类图

八种单例设计模式使用方式及优缺点
饿汉式

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

类变量instance,由于通过new关键字主动始用,会在类初始化时被收集进<clinit>方法
在多线程情况下不会被实例化多次,能够保证多线程环境下的唯一实例,但是如果一个类的成员占用资源比较多,使用这种方式就有所不妥,并且饿汉式单例也不能进行懒加载。
饿汉式变种
public final class Singleton{
private static Singleton instance = null;
static{
instance = new Singleton();
}
public static Singlton getInstance(){
return instance;
}
}

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

在Singleton类初始化的时候并不会导致instance实例化,在多线程环境下,会导致instance实例被实例化一次以上,不会保证单例的唯一性
懒汉式+同步方法
public final class Singleton{
private Singleton(){}
private static Singleton instance = null;
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}

采用懒汉式+数据同步的方式,既满足了懒加载又保证了单例的唯一性,但是由于同步方法在多线程环境下会使得在同一时刻只能有同一个线程访问,导致性能比较低
Double-Check
public final class Singleton{
Connection conn;
Socket socket;
private static Singleton instance = null;
private Singleton(){
this.conn;
this.socket;
}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton;
}
}
}
return instance;
}
}

Double-Check既满足了懒加载,又能保证实例的唯一性,提供了高效的数据同步策略,但是在多线程环境下,有可能出现空指针异常。
在Singleton的构造函数中,需要分别实例化conn和socket,还有Singleton自身,但是由于JVM在运行时的指令重排序和Happens-before规则,这三者的实例化顺序并无前后约束关系,极有可能instance最先被实例化,但是conn和socket还没有实例化。未完成实例化的实例,调用其方法将会抛出空指针异常。因此我们可以通过 private volatile static Singleton instance = null 使用volatile关键字来禁止指令重排序。
静态内部类
public final class Singleton{
private Singleton(){}
public static class Holder{
public static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return Holder.instance;
}
}

Singleton初始化的时候并没有创建其实例,Singleton在静态内部类中定义了实例,并且直接进行了实例化,当静态内部类主动引用的时候会被实例化,Singleton实例化的过程,在JVM程序编译器将其收集到<clinit>方法中,该方法是同步方法,同步方法可以保证内存可见性,JVM指令的顺序行和原子性。
枚举方式(https://blog.csdn.net/moakun/article/details/80688851
public final class Singleton{
private Singleton(){}
public enum EnumHolder{
INSTANCE;
private Singleton instance;
private EnumHolder(){
this.instance = new Singleton();
}
public static Singleton getSingleton(){
return instance;
}
}
public static Singleton getInstance(){
return EnumHolder.INSTANCE.getSingleton();
}
}

枚举单例实现方式比较精简,既能保证线程安全,又能实现懒加载,而且枚举可以避免反序列化破坏单例
我们知道普通的Java类在反序列化的过程中,回到用类的构造函数来初始化对象,所以即使单例中构造函数私有的,也会被反射给破坏掉。由于反序列化后的对象是重新new出来的,所以就破坏了单例,而枚举在在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 一. Java基础部分.................................................
    wy_sure阅读 3,774评论 0 11
  • 什么是单例模式? 在文章开始之前我们还是有必要介绍一下什么是单例模式。单例模式是为确保一个类只有一个实例,并为整个...
    听誓言碎了阅读 163评论 0 0
  • JAVA面试题 1、作用域public,private,protected,以及不写时的区别答:区别如下:作用域 ...
    JA尐白阅读 1,138评论 1 0
  • Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和...
    Java小辰阅读 959评论 0 5
  • 1 这是一个失去与告别的时代。 2 12日下午《明报》创办人、笔名金庸的武侠小说泰斗查良镛在香港殡仪馆设灵,丧礼以...
    孟寒max阅读 296评论 0 0