单例模式
饿汉式
public class hungry {
private hungry() {
System.out.println("I am hungry");
}
private static hungry instance = new hungry();
public static hungry getInstance() {
return instance;
}
public static void main(String[] args) {
hungry h1 = hungry.getInstance();
hungry h2 = hungry.getInstance();;
System.out.println(h2);
System.out.println(h1);
}
}
浪费内存空间
懒汉式
public class LazyMan {
private LazyMan() {
System.out.println("I am LazyMan");
}
private static LazyMan instance;
public static LazyMan getInstance() {
if (instance == null) {
instance = new LazyMan();
}
return instance;
}
}
但是多线程下这个写法会出现问题。
public class LazyMan {
private LazyMan() {
System.out.println("I am LazyMan");
}
private static LazyMan instance;
public static LazyMan getInstance() {
if (instance == null) {
instance = new LazyMan();
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
getInstance();
}).start();
}
}
}
可以看到实例被创建了多次,解决的方法很简单,加锁!
package single;
public class LazyMan {
private LazyMan() {
System.out.println("I am LazyMan");
}
private static LazyMan instance;
//双重判断
public static LazyMan getInstance() {
if (instance == null) {
synchronized (LazyMan.class) {
if (instance == null) {
instance = new LazyMan();
}
}
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
getInstance();
}).start();
}
}
}
但现在还有问题: new LazyMan不是一个原子性操作,分为三步:
- 分配内存空间
- 执行构造方法,实例化对象
- 把对象指向内存空间 那么就有可能存在一个指令重排现象,比如执行顺序变为1,3,2。那么会发生什么呢?