什么是单例模式
- 单例模式确保应用中,一个类最多只有一个实例
- 单例模式也提供访问此实例的全局访问点
- 单例模式实现中,使用了一个私有构造器,一个静态方法以及一个静态变量
为什么要用单例模式
java中静态全局变量也能做到被实例化一次
但是对于全局变量而言,这个全局变量对象可能在应用启动的时候就被创建,如果这个对象是资源密集型的,则长时间没使用,就对资源不是很友好。
单例模式可以使得对象延迟被创建,对于资源密集型的应用来说很重要。
单例模式的实现方式
- 简单的实现方式:
public class Singleton {
private static Singleton uniqueInstance;
// 其他有用的实例变量
private Singleton() {};
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
优点:符合单例模式的定义,满足单例模式的要求
缺点:在多线程的环境下,容易产生多个实例
- 多线程情况下的同步方式
public class Singleton1 {
private static Singleton1 uniqueInstance;
// 其他有用的实例变量
private Singleton1() {};
public static synchronized Singleton1 getInstance() { // synchronized设置成同步的
if (uniqueInstance == null) {
uniqueInstance = new Singleton1();
}
return uniqueInstance;
}
}
优点:同步方式可以解决多线程并发的问题
缺点:同步锁很重,容易带来性能低下的问题
- 饿汉模式,让JVM来保证实例的唯一性
public class Singleton2 {
private static Singleton2 uniqueInstance = new Singleton2(); // JVM来保证唯一性
private Singleton2() {};
public static Singleton2 getInstance() {
return uniqueInstance;
}
}
优点:让JVM来保证实例的问一下,可以解决多线程带来的并发问题
缺点:使用不够灵活
- 双重检查加锁
public class Singleton3 {
private volatile static Singleton3 uniqueInstance;
private Singleton3() {};
public static Singleton3 getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton3.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton3();
}
}
}
return uniqueInstance;
}
}
优点:可以解决同步过重的问题
缺点:至少得在java5以上才能运行
- 枚举方式实现单例
public enum SingletonEnum {
INSTANCE,
public void testMethod() {
System.out.println("执行了单例类的方法");
}
}
优点:真正做到线程安全,避免上述方法隐藏的问题
参考文档:单例模式加锁/枚举