单例模式的几种写法
懒汉式:
1、每次获取一个且唯一的对象。
public class SingleTon {
private static SingleTon instance;
private SingleTon(){
}
public static SingleTon getInstance() {
if(instance == null) {
instance = new SingleTon();
}
return instance;
}
}
2、适应多线程并发访问。
public class SingleTon {
private static SingleTon instance;
private SingleTon(){
}
public static SingleTon getInstance() {
synchronized (SingleTon.class) {
if(instance == null) {
instance = new SingleTon();
}
}
return instance;
}
}
3、第一次使用加锁,以后使用不再加锁。
public class SingleTon {
private static SingleTon instance;
private SingleTon(){
}
public static SingleTon getInstance() {
if(instance == null) {//第一次进来加锁,以后进来不再加锁
synchronized (SingleTon.class) {
if(instance == null) {//有多个线程同时进来,避免重复创建对象
instance = new SingleTon();
}
}
}
return instance;
}
}
4、instance = new SingleTon()实际上不是一个原子操作,这一步包括三件事:1、给SingleTon的实例分配内存 2、初始化SingleTon的构造方法 3、将instance指向分配的内存空间。
由于java编译器允许处理器乱序执行,2和3的顺序无法保证。如果顺序是1->3->2,并且在3执行完,2未执行之前,被切换到线程二,instance为非null,直接使用,会报错。所以使用volatile(volatile的作用参考https://www.cnblogs.com/dolphin0520/p/3920373.html)来修饰instance可以保证让instance每次都去主内存读取。
public class SingleTon {
private volatile static SingleTon instance;
private SingleTon(){
}
public static SingleTon getInstance() {
if(instance == null) {//第一次进来加锁,以后进来不再加锁
synchronized (SingleTon.class) {
if(instance == null) {//有多个线程同时进来,避免重复创建对象
instance = new SingleTon();
}
}
}
return instance;
}
}
饿汉式:
public class SingleTon {
private static SingleTon instance = new SingleTon();
private SingleTon() {
}
public static SingleTon getInstance() {
return instance;
}
}
使用静态内部类实现懒加载:
public class SingleTon {
private static class Single {
private static SingleTon instance = new SingleTon();
}
private SingleTon() {
}
public static SingleTon getInstance() {
return Single.instance;
}
}

浙公网安备 33010602011771号