解法一:只适合单线程环境(不好)

package test;

/**

* @author xiaoping

*

*/
public class Singleton {

private static Singleton instance=null;

private Singleton(){

}</br>
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> Singleton getInstance(){</br>
</span><span style="color: #0000ff;">if</span>(instance==<span style="color: #0000ff;">null</span><span style="color: #000000;">){</br>
instance</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Singleton();</br>
}</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> instance;</br>
}</br>

}

注解:Singleton的静态属性instance中,只有instance为null的时候才创建一个实例,构造函数私有,确保每次都只创建一个,避免重复创建。
缺点:只在单线程的情况下正常运行,在多线程的情况下,就会出问题。例如:当两个线程同时运行到判断instance是否为空的if语句,并且instance确实没有创建好时,那么两个线程都会创建一个实例。

解法二:多线程的情况可以用。(懒汉式,不好)

public class Singleton {

private static Singleton instance=null;

private Singleton(){

}</br>
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> Singleton getInstance(){
</span><span style="color: #0000ff;">if</span>(instance==<span style="color: #0000ff;">null</span><span style="color: #000000;">){</br>
instance</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Singleton();</br>
}</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> instance;</br>
}

}

注解:在解法一的基础上加上了同步锁,使得在多线程的情况下可以用。例如:当两个线程同时想创建实例,由于在一个时刻只有一个线程能得到同步锁,当第一个线程加上锁以后,第二个线程只能等待。第一个线程发现实例没有创建,创建之。第一个线程释放同步锁,第二个线程才可以加上同步锁,执行下面的代码。由于第一个线程已经创建了实例,所以第二个线程不需要创建实例。保证在多线程的环境下也只有一个实例。
缺点:每次通过getInstance方法得到singleton实例的时候都有一个试图去获取同步锁的过程。而众所周知,加锁是很耗时的。能避免则避免。

解法三:加同步锁时,前后两次判断实例是否存在(可行)

public class Singleton {

private static Singleton instance=null;

private Singleton(){

}</br>
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> Singleton getInstance(){</br>
</span><span style="color: #0000ff;">if</span>(instance==<span style="color: #0000ff;">null</span><span style="color: #000000;">){</br>
</span><span style="color: #0000ff;">synchronized</span>(Singleton.<span style="color: #0000ff;">class</span><span style="color: #000000;">){</br>
</span><span style="color: #0000ff;">if</span>(instance==<span style="color: #0000ff;">null</span><span style="color: #000000;">){</br>
instance</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Singleton();</br>
}</br>
}</br>
}</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> instance;
}

}

注解:只有当instance为null时,需要获取同步锁,创建一次实例。当实例被创建,则无需试图加锁。
缺点:用双重if判断,复杂,容易出错。

解法四:饿汉式(建议使用)

public class Singleton {

private static Singleton instance=new Singleton();

private Singleton(){

}</br>
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> Singleton getInstance(){</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> instance;</br>
}</br>

}

注解:初试化静态的instance创建一次。如果我们在Singleton类里面写一个静态的方法不需要创建实例,它仍然会早早的创建一次实例。而降低内存的使用率。

缺点:没有lazy loading的效果,从而降低内存的使用率。

解法五:静态内部内。(建议使用)

public class Singleton {

private Singleton(){

}</br>
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> SingletonHolder{</br>
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> Singleton instance=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Singleton();
}</br>
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> Singleton getInstance(){</br>
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> SingletonHolder.instance;</br>
}</br>

}

注解:定义一个私有的内部类,在第一次用这个嵌套类时,会创建一个实例。而类型为SingletonHolder的类,只有在Singleton.getInstance()中调用,由于私有的属性,他人无法使用SingleHolder,不调用Singleton.getInstance()就不会创建实例。
优点:达到了lazy loading的效果,即按需创建实例。

快速理解Java中的五种单例模式(转)的更多相关文章

  1. 快速理解Java中的五种单例模式

    解法一:只适合单线程环境(不好) package test; /** * @author xiaoping * */ public class Singleton { private static S ...

  2. 快速理解Java中的七种单例模式

    饿汉式(推荐) package concurencyv2.chapter1; public class SingletonV2 { private static final SingletonV2 i ...

  3. Java中的五种单例模式实现方法

    [代码] Java中的五种单例模式实现方法   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 2 ...

  4. Java中的五种单例模式

    Java模式之单例模式: 单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例. 特点: 1,一个类只能有一个实例 2 自己创建这个实例 3 整个系统都要使用这个实例 例: 在下面 ...

  5. java中的几种单例模式

    目前比较常见的有4种(DCL为懒汉模式的线程安全版本). 单例模式的实现一般需要满足以下条件: 1.构造方法私有化,实例属性私有化. 2.必须仅在类的内部完成实例的初始化过程. 3.提供公共静态方法, ...

  6. 5000字 | 24张图带你彻底理解Java中的21种锁

    本篇主要内容如下: 本篇文章已收纳到我的Java在线文档. Github 我的SpringCloud实战项目持续更新中 帮你总结好的锁: 序号 锁名称 应用 1 乐观锁 CAS 2 悲观锁 synch ...

  7. JDK学习---深入理解java中的HashMap、HashSet底层实现

    本文参考资料: 1.<大话数据结构> 2.http://www.cnblogs.com/dassmeta/p/5338955.html 3.http://www.cnblogs.com/d ...

  8. 【Java】深入理解Java中的spi机制

    深入理解Java中的spi机制 SPI全名为Service Provider Interface是JDK内置的一种服务提供发现机制,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用 ...

  9. java单例五种实现模式梳理

    java单例五种实现模式 饿汉式(线程安全,调用效率高,但是不能延时加载) 一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式.但是问题也比较明显.单例在 ...

随机推荐

  1. php中str_repeat函数

    php中str_repeat函数 一.作用 用于repeat str 二.实例:输出菱形 代码: <!DOCTYPE html> <html lang="en"& ...

  2. JS 在HTML页面显示当前日期

    代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <t ...

  3. Spring boot 解析jsp支持jsp热部署

    解析jsp并且支持jsp热部署 参考地址:https://www.wanpishe.top/detail?blogId=39875536-7d45-48ec-a7b5-f36b85c3a235

  4. mount---挂载文件系统

    挂载概念 Linux中的根目录以外的文件要想被访问,需要将其“关联”到根目录下的某个目录来实现,这种关联操作就是“挂载”,这个目录就是“挂载点”,解除次关联关系的过程称之为“卸载”. 注意:“挂载点” ...

  5. Excel 打开两个单独的页面

    方法: 一.打开一个excel,二."开始-程序-Microsoft Office" 打开一个Microsoft Office,文件打开需要用的文件 三 结果如上图所示

  6. 【2017 Multi-University Training Contest - Team 3】Kanade's sum

    [Link]:http://acm.hdu.edu.cn/showproblem.php?pid=6058 [Description] 给你n个数; 它们是由(1..n)组成的排列; 然后给你一个数字 ...

  7. c++操作当前窗体句柄

    句柄 这一概念是MFC里的一个类.MFC有专门的函数来获取窗体句柄. HWND hwnd; hwnd=CreateWindow("my own windowshandle",&qu ...

  8. 1.26 Python知识进阶 - 继承

    继承 继承(Inheritance)是面向对象的程序设计中代码重要的主要方法.继承是允许使用现有类的功能,并在无需重新改写原来的类的情况下,对这些功能进行扩展.继承可以避免代码复制和相关的代码维护等问 ...

  9. Android 多线程下载,断点续传,线程池

    你可以在这里看到这个demo的源码: https://github.com/onlynight/MultiThreadDownloader 效果图 这张效果图是同时开启三个下载任务,限制下载线程数量的 ...

  10. 用C#生成随机中文汉字验证码的基本原理

    前几天去申请免费QQ号码,突然发现申请表单中的验证码内容换成了中文,这叫真叫我大跌眼镜感到好笑,Moper上的猫儿们都大骂腾讯采用中文验证码.^_^  我不得不佩服腾讯为了防止目前网络上横行的QQ号码 ...