八种单例模式对比
1.什么是单例模式?
单例模式就是让一个类在系统内存中只有一个实例对象,通常用一个静态方法提供。
2.为什么要用单例模式?
对于频繁创建和销毁的对象,以及创建重量级对象,耗时多的对象,都会增加内存开销,通过单例模式可以提高系统性能,节约内存资源。
3.八种设计模式对比
Method1:饿汉式(静态常量法)
public class Singleton{
private Singleton() {}
private static final Singleton s = new Singleton();
public static Singleton getInstance() {
return s;
}
}
评论:该方式通过静态常量的方式提供实例,方法简洁,保证了线程安全,但是没有做到Lazy loading(懒加载),如果没有调用获取实例的方法,同时又加载了这个类(加载这个类的情况有很多),创建对象就造成了资源浪费,如果能确保一定用到这个实例,该方法推荐使用,JDK中Runtime类就是通过这种方法获取实例。
Method2:饿汉式(静态代码块)
public class Singleton{
private Singleton() {}
private static Singleton s;
static{
s = new Singleton();
}
public static Singleton getInstance() {
return s;
}
}
评论:该方法通过静态代码块的方法获得实例,静态代码块在类加载时执行,优缺点同Method1。
Method3:懒汉式-1
public class Singleton{
private Singleton() {}
private static Singleton s;
public static Singleton getInstance() {
if (s == null) {
s = new Singleton();
}
return s;
}
}
评论:该方式做到了懒加载,单线程使用没有问题;但是在多线程情况下,可能会创建多个实例,不能保证线程安全,不可用。
Method4:懒汉式-2
public class Singleton{
private Singleton() {}
private static Singleton s;
public static synchronized Singleton getInstance() {
if (s == null) {
s = new Singleton();
}
return s;
}
}
评论:该方式通过同步方法获取实例,保证了线程同步和懒加载,但是每次获取实例都要调用同步方法,造成效率低下,但从效率上不推荐使用。
Method5:懒汉式-3
public class Singleton{
private Singleton() {}
private static Singleton s;
public static Singleton getInstance() {
if (s == null) {
synchronized (Singleton.class) {
s = new Singleton();
}
}
return s;
}
}
评论:该方式通过同步代码块获取实例,保证了懒加载,但是不能保证线程同步,多线程情况下不可用。
Method6:双重检查
public class Singleton{
private Singleton() {}
private static volatile Singleton s = null;
public static Singleton getInstance() {
if (s == null) {
synchronized (Singleton.class) {
if (s == null) {
s = new Singleton();
}
}
}
return s;
}
}
评论:该方式实例变量用volatile 修饰,在变化时立马同步到主内存,保证了线程同步、懒加载,也解决了效率问题,推荐使用。
Method7:静态内部类
public class Singleton{
private Singleton() {}
static class Single {
private static final Singleton s = new Singleton();
}
public static Singleton getInstance() {
return Single.s;
}
}
评论:该方式借助静态内部类的优势,加载Singleton的时候不加载Single ,保证了懒加载;Single类在使用的时候才加载,且只加载一次,保证了线程同步和效率问题,推荐使用。
Method8:枚举
enum Singleton{
INSTANCE;
}
评论:该方式通过Singleton.INSTANCE得到实例,实例唯一,线程安全,推荐使用。
总结:
1.实现层面,以上八种方法在单线程下都是可行的;
2.多线程层面,Method3和Method5不可用;
3.效率层面,同步方法Method3不推荐;
4.懒加载层面,两种饿汉式Method1,2不推荐;
5.多方面考虑Method6,7,8推荐使用;
作者:Darren
电话:15110448224
QQ:603026148
以上内容归Darren所有,如果有什么错误或者不足的地方请联系我,希望我们共同进步。