java设计模式之-----单例设计模式

1.定义

单例设计模式:顾名思义,一个类只能产生一个实例,也就是说一个类只能有一个对象。就像古代的皇帝一样,只能有一个,多一个也不可以,这就是单例设计模式。

2.步骤及要点(注意)

  • 私有化构造函数
  • 提供一个本类的实例
  • 提供一个对外的供外界访问的方法

实现过程

  1. 最简单的单例模式
        (1)恶汉式
     public class SingelInstance {

    // 私有化构造函数
    private SingelInstance() {

    }

    // 产生一个实例对象
    private static SingelInstance singleInstance = new SingelInstance();

    // 提供一个供外界访问的方法
    public static SingelInstance getInstance() {
        return singleInstance;
    }
}
(2)懒汉式
 public class SingelInstance1 {

    private SingelInstance1() {

    }

    private static SingelInstance1 singelInstance1;

    public static SingelInstance1 getSingelInstance1() {
    //假如同步关键字
        synchronized (SingelInstance1.class) {
            if(singelInstance1 == null){
                singelInstance1 = new SingelInstance1();
            }
        }
        return singelInstance1;
    }

}

比较: 恶汉式与懒汉式的区别仅在于先 new 与后 new 的问题,从名字就可以看出.懒汉式可以在需要的时候再new 对象,而恶汉式则是不管什么先 new 了一个对象.懒汉式的get 方法中要注意多线程的同步问题.为什么?java中new 一个对象不是简单的一个new 就能 new 出来的,只是我们自己这么觉得,其实,在编译后的执行的步奏中要经过几部才能产生出一个对象,假如不加入同步,就可能多个线程进入get 方法中产生多个对象.
注意: synchronized 关键字中不能用this关键字,为什么? 因为这个方法是静态的,静态优先于非静态,随着类的加载而加载,当对象还没产生时,静态方法就已经载入了,所以不能用this关键字,但是可以用类的class对象,原因前面已经说了.

(3)懒汉式(双重非空判断)

 public class SingelInstance2 {

    private SingelInstance2() {

    }

    private static SingelInstance2 singelInstance2;

    public static SingelInstance2 getSingelInstance2() {
    //双重非空判断
        if (singelInstance2 == null) {

            synchronized (SingelInstance1.class) {

                if (singelInstance2 == null) {
                    singelInstance2 = new SingelInstance2();
                }

            }
        }
        return singelInstance2;
    }

}

为什么这样做: 在未加入双重非空判断的实例中,多个线程每次调用的get 方法中都要对对象上锁,事实上,只有在第一次创建的时候才需要对对象上锁,之后就不要了,因为对象已经new 出来了,之后只要直接返回就可以了,所以多加入一层非空判断有利于性能的提升.
分析: 假如现在有两个线程,A, B.
A,b线程同时进入了第一个if 判断,
A首先进入同步代码块,singelInstance2 为null,紧接着new 出了一个对象.由于jvm的优化机制,jvm给SingelInstance2 分配了存储空间,并复制给了成员变量singelInstance2 .(此时还没有实例化singelInstance2 ),然后A 离开了同步代码块.
此时B进入了同步代码块,由于此时singelInstance2 不为空,紧接着B出去了,并return 了singelInstance2.
此时B打算使用singelInstance2 ,但是singelInstance2 还没有实例化成对象,于是错误发生了.

(4) 静态内部类单例模式

     public class SingelInstance3 {

    private SingelInstance3() {

    }

    private static class SingelInstanceFactory {
        private static SingelInstance3 singelInstance3 = new SingelInstance3();
    }

    public SingelInstance3 getSingelInstance3() {
        return SingelInstanceFactory.singelInstance3;
    }
}

为什么这样可以:
jvm内部机制能够保证一个类被加载的时候,这个类加载的过程式互斥的,这样当我们第一次调用getSingelInstance3
的时候,jvm能够保证singelInstance3
只被创建一次,并且会保证把赋值给singelInstance3内存空间初始化完毕,这样我们就解决了刚才的问题,同时该方法也只会在第一次调用的时候使用互斥机制,同时也解决了性能上的问题.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值