一、懒汉式(线程不安全)
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
介绍:线程不安全,在多线程情况下容易创建多个实例。
二、懒汉式(线程安全)
public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
介绍:虽然线程安全,但是不够高效。
三、双重检验锁
public static Singleton getSingleton() { if (instance == null) { //Single Checked synchronized (Singleton.class) { if (instance == null) { //Double Checked instance = new Singleton(); } } } return instance ; }
介绍:双重检验锁机制比懒汉式(线程安全)要高效很多,因为它不用对instance不为空的情况进行同步。这段代码看起来似乎很完美,但很可惜,还是存在问题。instance=new Singleton() 这并非是一个原子性质的操作,事实上在JVM中做了如下三件事:
- 给instance分配内存
- 调用构造函数初始化成员变量
- 将instance对象指向分配的内存(此步骤完成instance即为非空)
但是在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。
四、双重检验锁(volatile)
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; } }
介绍:使用 volatile 的原因是可以保证线程在本地不会存有 instance 的副本,每次都是去主内存中读取。这里使用volatile的一个主要原因就是volatile可以禁止JVM指令重排序。
五、饿汉式
public class Singleton{ //类加载时就初始化 private static final Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } }
介绍:这种方法非常简单,因为单例的实例被声明成 static 和 final 变量了,在第一次加载类到内存中时就会初始化,所以创建实例本身是线程安全的。缺点是它不是一种懒加载模式。比如 Singleton 实例的创建是依赖参数或者配置文件的,在 getInstance() 之前必须调用某个方法设置参数给它,那样这种单例写法就无法使用了。
五、静态内部类
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
介绍:这种写法仍然使用JVM本身机制保证了线程安全问题;由于 SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖 JDK 版本。
六、枚举
public enum EasySingleton { INSTANCE; EasySingleton(){ } }
介绍:我们可以通过EasySingleton.INSTANCE来访问实例,这比调用getInstance()方法简单多了。创建枚举默认就是线程安全的,所以不需要担心double checked locking,而且还能防止反序列化导致重新创建新的对象。
相关推荐
一个简单的java工程,包含注释,一目了然,其中包含了单例模式的所有实现方式,懒汉式,饿汉式,双重校验,枚举,静态内部类等方式实现单例。
Java 单例模式 懒汉模式 //懒汉式 多线程中不可以保证是一个对象
作为对象的创建模式, 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 PPT详细了单例模式的实现和使用场景
Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式Java SE程序 单例模式...
Java单例模式,其中:单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种
java单例模式的例子java单例模式的例子java单例模式的例子
详细讲解了Java单例模式的几种实现方式,并有详细的示例配合讲解.
Java设计模式-单例模式(懒汉和恶汉)
java单例模式开发的7中写法,网上搜索的,可以看看
源码 博文链接:https://tianlihu.iteye.com/blog/747737
代码中演示了Java设计模式中的单例模式,其中包括饿汉单例模式,懒汉单例模式以及序列化饭序列化单例模式。在实际的开发中,可以直接借鉴使用。
Java单例模式Java单例模式Java单例模式Java单例模式
通过单例模式实例化获取propertyUtil 工具包实例,高效加载配置文件,java语言编写。通过单例模式实例化获取propertyUtil 工具包实例,高效加载配置文件,java语言编写。通过单例模式实例化获取propertyUtil 工具包...
实用Java的单例模式,实用于Java学习者 单例模式 单例模式
java Singleton单例模式 java Singleton单例模式
目录 单例模式的概念 单例模式的要点 单例模式类图 单例模式归类 单例模式的应用场景 单例模式解决的问题 单例模式的实现方式 单例模式实现方式对比 单例模式的概念 单例模式,顾名思义就是只有一个实例,并且由它...
编写一个类LimitInstanceClass,该类最多可以实例化指定个数实例。实例的个数用配置文件InstanceLimit.cfg指定。例如,如果InstanceLimit.cfg的内容为2,则LimitInstanceClass最多可以同时存在2个对象。...
java单例模式连接数据库源码.可以直接引用只需加入相应的mysql 或 oracle的驱动,修改源码的连接地址用户名及密码。
java单例模式及实现