设计模式之单例模式

类的计划生育(单例模式)

  • 概念
  • 类图
  • 代码实例

概念

允许类产生仅且只有一个对象,如何在多线程环境下实现这一功能应该是这个类来控制的,所以需要实现产生单个实例关键点有以下几点

1、构造器设置为private

2、有一个包含本来的字段,并且是static类型,如果采用double check方式还需要增加volatile修饰保证可见性和有序性

3、创建对象的时机(类一加载时就创建这个实例是饥饿式 在使用该对象的时候创建这个实例为饱汉式)

4、提供一个全局获取实例方法,由于不能在外部new那么该方法为static类型

5、在多线程环境下依然要保证只能有且仅有一个实例

类图

在这里插入图片描述

SingletonObject:单例对象类,类的内部进行控制如何实现仅仅返回一个实例逻辑

Client:客户端测试

代码实例

SingletonDoubleCheck 使用双重判断+synchronized+volatile保证多线程下依然获取到单个实例对象

/**
 * 为了能在多线程环境下也能保证线程安全,使用double-check双重检测
 */
public class SingletonDoubleCheck {

  //volatile 保证可见性,有序性
  private volatile static SingletonDoubleCheck singletonDoubleCheck;

  //避免外部通过new来创建对象
  private SingletonDoubleCheck() {

  }

  public static SingletonDoubleCheck getInstance() {
    //此处判断避免了每次都需要加上锁,提高了获取对象性能
    if (singletonDoubleCheck == null) {
      synchronized (SingletonDoubleCheck.class) {
        if (singletonDoubleCheck
            == null) {//如果不使用double check,会导致多线程并发获取实例时,多次创建对象,使用 volidate也避免了指令重排和可见性(如果不用volidate修饰//new 对象会经历三个过程 1、开辟内存空间 2、初始化对象值 3、将对象地址赋给引用 如果顺序变成了 1->3->2就会导致某个线程获取到的对象没有初始化)
          singletonDoubleCheck = new SingletonDoubleCheck();
        }

      }
    }
    return singletonDoubleCheck;
  }
}

SingletonObject 使用类加载器本身就实现了线程安全机制(类仅被加载一次)实现多线程下获取单个实例逻辑

public class SingletonObject {
    //饥汉模式 天生就具有线程安全性,类加载器控制一个类只被加载一次
    private static SingletonObject singletonObject = new SingletonObject();

    //避免外部通过new来创建对象
    private SingletonObject() {
    }

    public static SingletonObject getSingletonObj() {
        //return singletonObject;
        return Holder.INSTANCE;
    }

    //使用静态类建立单例,因为类只被加载器加载一次
//饱汉模式,使用的时候才创建,这样和double-check比起来不用加锁同步了
    private static class Holder {
        private static SingletonObject INSTANCE = new SingletonObject();
    }

}

Client 测试类

/**
 * @author duanyimiao
 * @create 2018-10-19 10:28 PM
 * @description
 **/
public class Client {
    public static void main(String[] args) {
        SingletonDoubleCheck singletonDoubleCheck1 = SingletonDoubleCheck.getInstance();

        SingletonDoubleCheck singletonDoubleCheck2 = SingletonDoubleCheck.getInstance();

        System.out.println(String.format("by class loader only create one object", singletonDoubleCheck1 == singletonDoubleCheck2 ? "is" : "is not"));

        SingletonObject singletonObject1 = SingletonObject.getSingletonObj();

        SingletonObject singletonObject2 = SingletonObject.getSingletonObj();

        System.out.println(String.format("by double check only create one object", singletonObject1 == singletonObject2 ? "is" : "is not"));

    }
}

输出结果

by class loader is only create one object
by double check is only create one object
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值