// 从今往后的两个月我会将设计模式学习资料整理成一个系列供我自己和大家参考
单例模式思想
某个类中只能存在一个对象实例,且该类只能提供一个取得该对象实例的方法
饿汉式
1. 静态常量
class Single {
private Single() {}
private final static Single instance = new Single();
public static Single getInstance() {
return instance;
}
}
优点:写法简单,在类装载时就完成实例化,没有多线程问题
缺点:若从未使用过这个实例,则会造成内存浪费
2. 静态代码块
class Single {
private Single() {}
private final static Single instance;
static {
instance = new Single();
}
public static Single getInstance() {
return instance;
}
}
将实例化放在了静态代码块中,优缺点和静态常量创建的方式一样。
懒汉式
1. 线程不安全
class Single {
private Single() {}
private static Single instance;
public static Single getInstance() {
if(instance==null) {
instance = new Single();
}
return instance;
}
}
在实际开发中会有线程安全问题,不能使用
2. 线程安全(同步方法)
将线程不安全的getInstance方法加锁
public static synchronized Single getInstance() {
if(instance==null) {
instance = new Single();
}
return instance;
}
上述方法虽然解决了线程安全问题,但由于每一次获取实例都要进行同步,效率低下,实际开发中不推荐使用
而且由于new Single()会造成指令重排,所以多线程环境下也无法保证单例
3. 线程安全(双重检查)
private static volatile Single instance;
public static Single getInstance() {
if(instance==null) {
synchronized(Single.class) {
if(instance==null) {
instance = new Single();
}
}
}
return instance;
}
volatile的作用:
- 防止系统对instance进行指令重排,
- 通知各个线程instance的变化(可见性),让修改值立即更新到主存
4. 线程安全(静态内部类)
静态内部类只有当被调用其内部的方法时才会被装载,从而实现懒加载
class Single {
private Single() {}
private static class SingleInstance {
private final static Single instance = new Single();
}
public static Single getInstance() {
return SingleInstance.instance;
}
}
5. 线程安全(枚举)
enum Single {
INSTANCE;
public void method() { ... }
}
// 使用
Single instance = Single.INSTANCE;
instance.method();