【Java基础】单例

双检测+volatile

private volatile static Sington instance;
public static Singleton getInstance() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }

双检测:线程同步;
同步代码块:性能;
volatile:避免指令重排;
对于s = new Singleton();可以分解为3个步骤:
1 memory=allocate();// 分配内存 相当于c的malloc;
2 ctorInstanc(memory) //初始化对象;
3 s=memory //设置s指向刚分配的地址;
上面的代码在编译器运行时,可能会出现重排序 从1-2-3 排序为1-3-2,在多线程下就会出现问题,例如现在有2个线程A,B;线程A在执行第5行代码时,B线程进来,而此时A执行了 1和3,没有执行2,此时B线程判断s不为null 直接返回一个未初始化的对象,就会出现问题。有人说synchronized不是可以禁止重排序吗?这只是假象,是因为不加锁后是单线程,这种情况下无论重排序或者不重排序,结果都是一样的,synchronized并不是禁止了重排序,而是即使重排序,也不影响其结果!
对变量加上关键字volatile后,指令不会重排,就不会出现这样的问题。

静态内部类:

private SingleTon(){
}
private static SingleTonHolder{
	public static SingleTon instance = new SingleTon();
}
public static SingleTon getInstance() {
	return SingleTonHolder.instance;
}

1、静态变量在类的加载过程中就会进行初始化,静态代码块也是在类的加载过程中就会执行。
2、静态内部类和静态方法一样,静态方法只有被调用的时候才会执行,而静态内部类是只有在第一次调用的时候才会进行初始化。
顺便提一波类加载过程:
1、静态变量的初始化是在类加载过程中的准备阶段,但是这里仅仅是开辟内存空间,和赋初始值(比如 static int i = 100,这里会给i赋初始值0),真正在赋值是在类加载过程中的初始化阶段。
2、初始化阶段会进行静态变量的赋值,和静态代码块的执行操作。
初始化阶段是可选的,当使用Class.forName(String name, boolean initialize, ClassLoader loader)这个方法的时候,第二个参数为false的时候,就不会进行初始化,这个时候也不会有对静态变量的赋值,以及静态代码块的执行操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值