java 单例模式下属性_设计模式之一单例模式(java实现)

学习一下各种设计模式,看以后的用不用得上╮(╯_╰)╭

1. 饱汉式/**

* 饱汉式

* 1. 构造器私有化

* 2. 静态的私有变量instance

* 3. 静态的public方法 */public class Singleton {private static Singleton instance = new Singleton();private Singleton() {

}public static Singleton getInstance() {return instance;

}

}

懒汉式缺点:不管用不用这个对象,都会实例化,浪费资源;

2 饿汉式/**

* 饿汉式

* 只有在需要获取实例的时候,才会去实例化 */public class Singleton {private static Singleton instance;private Singleton() {

}public static Singleton getInstance() {if (instance == null) {

instance = new Singleton();

}return instance;

}

}

恶汉式也带来了问题,就是线程不安全

3. 对饿汉式+synchronized/**

* 饿汉式+synchronized

* 只有在需要获取实例的时候,才会去实例化 */public class Singleton {private static Singleton instance;private Singleton() {

}public synchronized static Singleton getInstance() {if (instance == null) {

instance = new Singleton();

}return instance;

}

}

在方法上加锁会锁住整个方法,继续优化一下,只是给new对象的部分代码加锁:/**

* 饿汉式+synchronized同步代码块

* 只有在需要获取实例的时候,才会去实例化 */public class Singleton {private static Singleton instance;private Singleton() {

}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {

instance = new Singleton();

}

}return instance;

}

}

但是在同步代码块这样的方式有产生了问题:线程A和线程B都执行到了同步代码块这里,线程A先进去,实例化对象instance,释放锁,然后线程B才进去,于是也实例化了一个instance,于是就有两个实例了,线程不安全

4. 双重检测锁/**

* 双重检测锁

*

*/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;

}

}

但是上面双重检测的方式在超高并发的环境下也有问题,涉及到JVM层面指令重排,这个双重检测单例模式加不加volatile是个经典面试题

举个例子:Singleton instance = new Singleton() 这条指令虽然我们程序员看起来就是一条指令,但是在jvm层面却是会分解成三条

(1)在java堆中分配空间,创建对象

(2) 给创建的对象初始化赋值

(3)在java栈中创建局部变量instance,指向java堆中的对象

在上面(2)和(3)因为指令重排可能交换了顺序,执行过程就是(1)-->(3)-->(2),当线程A执行到(1)->(3)的时候,此时instance指向的是一个半成品的实例,因为这个实例中的属性值还没有初始化;

此时线程B来调用Singleton.getInstance()就会发现跳过了里面的if语句,直接返回了instance实例,于是在线程B中调用该实例的方法的时候就会出问题(半成品的对象是什么呢,想一下类加载机制,加载,链接(验证,准备,解析),初始化,在加载,链接之后,初始化之前的对象就是半成品的)

可以使用volatile关键字进行优化,禁止指令重排;

5.1  双重检测锁+volatile实现单例(完美版)/**

* 双重检测+volatile */public class Singleton {private static volatile Singleton instance;private Singleton() {

}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {

instance = new Singleton();

}

}

}return instance;

}

}

5.2 枚举实现(完美版)/**

* 枚举方式实现 */public enum SingletonEnum {

instance;

}

5.3 静态内部类的方式实现单例(完美版)/**

* 静态内部类实现单例 */public class Singleton {private static Singleton instance;private Singleton() {

}private static class SingletonHelper {private static final Singleton singleton = new Singleton();

}public static Singleton getInstance() {return SingletonHelper.singleton;

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值