单例模式有几种经典的用法,如懒汉,恶汉,双重校验锁,枚举和静态内部类。下面为大家分别介绍一下。如不清楚的或有疑问的,请留言回复。感觉不错的,欢迎各位关注技术布道者头条号,不断为大家分享干货。
Java设计模式之单例模式UML示例图
1、懒汉式单例模式
public class Singleton {
private static Singleton instance = null;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种写法能够在多线程中很好的工作,而且也确实在初次使用时才初始化,但是,每次实例化singleton实例的时候都有一个试图去获取同步锁的过程。
加锁太耗时,不是最佳方式,尽量避免。
2、双重校验锁式单例模式
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
这个是懒汉式单例模式的升级优化,只有当instance为null时,需要获取同步锁,创建一次实例。当实例被创建,则无需试图加锁。
但在jdk的里程碑版本1.5之后就变得很有意义 而且现在以及被广泛使用 因为引入了修饰符volatile。这也是为什么说jdk1.5才能使用双重校验
3、饿汉式单例模式
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。
声明的final修饰符保证instance不会被其他程序所修改。
4、静态内部类式单例模式
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
定义一个私有的内部类,在第一次用这个嵌套类时,会创建一个实例。而类型为SingletonHolder的类,只有在Singleton.getInstance()中调用,由于私有的属性,他人无法使用SingleHolder,不调用Singleton.getInstance()就不会创建实例。这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,这种方式即可以实现懒加载,又可以保证线程安全,是个人推荐的单例使用方式。
它跟恶汉式单例模式不同的是:恶汉式单例模式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。而且Singleton的实例化在加载SingletonHolder类时进行初始化instance。
5、枚举式单例模式
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。但实际工作中很少见到这种使用方式。
Java设计模式
感觉有帮助的,欢迎关注、转发、收藏,楼下点赞,大家的鼓励是我们前进的动力;有不清楚或疑问的,请留言,大家一起交流。
本文由“技术布道者”发布,2017年04月24日