现在的位置: 首页 > 操作系统 > 正文

Java设计模式-单例模式

2020年02月13日 操作系统 ⁄ 共 2242字 ⁄ 字号 评论关闭

相信大家去面试的时候,经常被问到单例模式的有关问题吧,今天我们就来好好总结一下 一 懒汉式

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

相信大家对这段代码再熟悉不过了,懒汉式的意思就是每次在调用getInstance方法时,才去new一个Singleton的实例,但是很明显,按上面这样写有问题啊,线程不同步啊,那么怎么办呢

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

在getInstance方法之前加上synchronized不就解决了,但是这样,每次调用getInstance都会同步,而我们只是希望在第一次new Singleton()的时候同步即可,一旦instance不为空了,就不用再同步了,那么怎么做呢

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

在代码块利用锁,并且要加上双重检测,因为两个线程很可能同时执行到第一个判空的地方,可能判断都为空,就都会进入下面的代码里,就会生成两个对象,所以要加上双重锁定,但是这样就没问题了吗,当然不是,我们都知道Java内存模型中有无序写的机制,instance = new Singleton(); 这行其实做了两个事情:1、调用构造方法,创建了一个实例。2、把这个实例赋值给instance这个实例变量。可问题就是,这两步jvm是不保证顺序的。也就是说。可能在调用构造方法之前,instance已经被设置为非空了 比如顺序被重排了,先保证instance 不为null,后面才调用构造函数初始化,这个时候另外一个线程判断instance 不为空,直接返回instance ,这样就会有问题,那么怎么解决这个问题呢,我们知道 volatile关键字可以在instance 赋值的时候,禁止重排序

public class Singleton { private volatile static Singleton instance; //声明成 volatile private Singleton (){} public static Singleton getSingleton() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }

这样这个问题就解决了,但是是不是觉得很累,下面给出一种完美的解决方法,利用静态内部类

public class Singleton { private static class SingletonHolder{ private static Singleton instance = new Singleton(); } private Singleton() { } //获取单例对象实例 public static Singleton getInstance() { return SingletonHolder.instance; } }

我们知道,静态内部类只有在getInstance里第一次被调用的时候才加载,实现了懒加载,而且加载过程是线程安全的,所以一般用这种方法来实现懒汉式单例子

二 饿汉式

//饿汉式 public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } }

在类加载的时候就new好对象,这样也不存在线程安全问题,但是饿汉式也有问题,如果构造的单例很大,构造完又迟迟不使用,会导致资源浪费。

总结:推荐使用懒汉式静态内部类的方式实现单例模式,好了,设计模式-单例模式就总结到这里,如有问题,欢迎指正,谢谢。

本文永久更新链接地址:http://www.xuebuyuan.com/Linux/2016-11/137250.htm

以上就上有关Java设计模式-单例模式的相关介绍,要了解更多Java设计模式,单例模式 ,Java设计模式-单例模式,编程,Linux编程,Linux Shell,Android,Android教程,JAVA,C语言,Python,HTML5内容请登录学步园。

抱歉!评论已关闭.