原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755322.html

一、概述

Java中单例有7种写法,这个是在面试中经常被问到的内容,而且有时候还要求手写单例实现方式。所以我们有必要认真的了解一下这七种写法。

二、七种实现

2.1 懒汉式——线程不安全

public class SingletonOne {
public static SingletonOne singleton;
private SingletonOne() {}
public static SingletonOne getSingleton() {
if (singleton == null)
return new SingletonOne();
return singleton;
}
}

懒汉式实现了懒加载,但是线程不安全,基本不会使用。

2.2 懒汉式——线程安全

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

在第一种的基础上加了个synchronized,保证线程安全,同时实现了懒加载,只是效率不高。

2.3 饿汉式

public class SingletonThree {
public static SingletonThree singleton = new SingletonThree();
private SingletonThree () { }
public static SingletonThree getSingleton() {
return singleton;
}
}

由于实例优先提供,不存在线程安全问题,但是没有实现懒加载。

2.4 饿汉式——变种

public class SingletonFour {
public static SingletonFour singleton;
static {
singleton = new SingletonFour();
}
private SingletonFour () { }
public static SingletonFour getSingleton() {
return singleton;
}
}

其实和之前的一样,仅仅是将单例的创建挪到了静态块。

2.5 静态内部类式

public class SingletonFive {
private static class SingletonHolder {
private static SingletonFive singleton = new SingletonFive();
}
private SingletonFive () {}
public static final SingletonFive getSingleton(){
return SingletonHolder.singleton;
}
}

静态内部类保证了懒加载,单例实例优先提供又保证了线程安全性,较实用。

2.6 枚举式

public enum SingletonSix {
SINGLETON;
}

枚举的天然特性保证了单例,天然的私有构造器,天然的线程安全性,未被大规模使用的原因是枚举出现的有点晚。

2.7 双重校验锁式

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

注意:

  1. volatile的使用,为了防止暴露一个未初始化的不完整单例实例;
  2. 双重判空校验,第一个判断避免了频繁的加锁,第二个判断可以拦住多余的创建实例的线程;
  3. 加锁,保证了线程安全(只有一个实例)

这种实现方式是经常出现在面试题中的,而且经常会要求手写。

三、总结

上面罗列的7种设计模式中第1种线程不安全,可以排除在外,第3、4种其实是一种,这样下来其实可以简化为5种方式:懒汉、饿汉、静态内部类、枚举、双重校验锁。

Java基础系列-单例的7种写法的更多相关文章

  1. 转载:java基础之单例

    转载:https://blog.csdn.net/goodlixueyong/article/details/51935526 https://www.cnblogs.com/cielosun/p/6 ...

  2. Java并发编程中的设计模式解析(二)一个单例的七种写法

    Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ...

  3. java基础28 单例集合Collection下的List和Set集合

    单例集合体系: ---------| collection  单例集合的根接口--------------| List  如果实现了list接口的集合类,具备的特点:有序,可重复       注:集合 ...

  4. java基础27 单例集合Collection及其常用方法

    1.集合 集合是存储对象数据的集合容器 1.1.集合比数组的优势 1.集合可以存储任意类型的数据,数组只能存储同一种数据类型的数据    2.集合的长度是变化的,数组的长度是固定的 1.2.数组:存储 ...

  5. java单例的几种写法

    转载出处:http://cantellow.javaeye.com/blog/838473 第一种(懒汉,线程不安全): public class Singleton { private static ...

  6. 「Android」单例的五种写法

    单例 发现博客园可以很好的设置自己的博客文章的展示,很开心,然后特此发一篇 其实这几种写法大家应该都会的,就权当拿来记录一下吧,以后复习巩固也比较方便. 这篇文章中的代码,来自一篇视频(我想找视频贴上 ...

  7. java23种设计模式之二: 单例设计模式(6种写法)

    目的:在某些业务场景中,我们需要某个类的实例对象的只能有一个,因此我们需要创建一些单例对象. 本文共有6种写法,仅供参考 1.饿汉式 优点: 在多线程情况下,该方法创建的单例是线程安全的(立即加载) ...

  8. .NET Core中延迟单例另一种写法【.NET Core和.NET Framework的beforefieldinit差异】

    1.BeforeFieldInit是什么 前段时间在反编译代码时无意间看到在类中有一个BeforeFieldInit特性,处于好奇的心态查了查这个特性,发现这是一个关于字段初始化时间的特性[提前初始化 ...

  9. java单例的几种实现方法

    java单例的几种实现方法: 方式1: public class Something { private Something() {} private static class LazyHolder ...

随机推荐

  1. Linux 串口工具 lsz lrz 移植

    //之前写的,刚才不小心误删了,所以重新再发出来. 1 下载源码包 首先下载最新版的lrzsz,地址:https://ohse.de/uwe/software/lrzsz.html.下面以 0.12. ...

  2. 路由总结之静态、RIP、OSPF、IS-IS、BGP和策略路由

    路由无疑是当今网络的核心,看到浩如烟海的网络资料,可以让人皓首穷经啊,而且都是浩浩荡荡几百页,所以想搞简单点. 静态路由 静态路由无疑是最简单,也是最基本的. Ip route-static(指定是静 ...

  3. 版本控制系统之基于httpd搭建私有git仓库

    在上一篇博客中,我们主要聊到了git的基本工作原理和一些常用的git命令的使用:回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13787701.html:今天我 ...

  4. Java-JDK动态代理(AOP)使用及实现原理分析

    Java-JDK动态代理(AOP)使用及实现原理分析 第一章:代理的介绍 介绍:我们需要掌握的程度 动态代理(理解) 基于反射机制 掌握的程度: 1.什么是动态代理? 2.动态代理能够做什么? 后面我 ...

  5. lua 1.1 源码阅读总结

    GC 1. 怎么回收的lua 中所有已经分配的数据都会用一些指令的数据结构来记录,当需要回收时,先遍历当前栈内所有 object,把 ref 标志位打上 1,遍历符号表(这部分不能回收),反符号表中的 ...

  6. 多测师讲解接口测试 _fiddler无法打开浏览器_高级讲师肖sir

    错误现象: 打开fi'd'dler以后浏览器无法打开,关闭fiddler之后可以打开浏览器 解决方案: 1. 2. 在点击确定

  7. 三门峡6378.7939(薇)xiaojie:三门峡哪里有xiaomei

    三门峡哪里有小姐服务大保健[微信:6378.7939倩儿小妹[三门峡叫小姐服务√o服务微信:6378.7939倩儿小妹[三门峡叫小姐服务][十微信:6378.7939倩儿小妹][三门峡叫小姐包夜服务] ...

  8. c3算法

    # L(G) = [G] + [O] # G = [O] # = GO # L[E] = EO # L[F] = [F] + [GO] # F = [GO] # = FGO # L[B] = [B] ...

  9. Promises/A+规范

    为什么需要异步编程方式 一个函数执行之后,在它后面顺序编写的代码中,如果能够直接使用它的返回结果或者它修改之后的引用参数,那么我们通常认为该函数是同步的. 如果一个函数的执行结果或者其修改的引用参数, ...

  10. 子网划分和VLAN

    子网划分 IP地址的结构和分类 根据tcp/ip协议,连接在Internet上的每个设备都必须有一个IP地址,它是一个32位二进制数,为了方便人类识别,我们将它用点分十进制表示,每8位分为一段. IP ...