单例模式(Singleton):是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。
1、懒汉式
线程不安全,当有多个线程并行调用 getInstance() 的时候,就会创建多个实例。
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2、饿汉式
当类装载的时候就会创建类的实例,不管你用不用。因为单例的实例被声明成 static 和 final 变量了,所以运行时环境中始终只存在一个实例。
但它的缺点是不是懒加载。
public class Singleton{
//类加载时就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
3、双重加锁式
在headfirst设计模式中介绍的一种方式,形式较为复杂点。
双重锁的主要目的是解决每次获取实例的时候都需要进行线程等待,只有在第一次实例化时,才启用同步机制,提高了性能。
但是使用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;
}
}
4、静态内部类
比较推崇的做法之一,据说是Google大牛的发明的。这种做法巧妙的使用JVM本身机制保证了线程安全问题。
这种方法读取实例的时候不会进行同步,没有性能缺陷。
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
5、Enum枚举方式
《Effective Java》上所推荐的方法。一般情况下这是实现Singleton的最佳方法。
最大的优点就是简单,并且提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。
public enum EnumSingleton{
INSTANCE;
}
就这么简单,你可以使用EnumSingleton.INSTANCE调用它。