详解单例模式

单例模式分为饿汉跟懒汉两种模式
1)饿汉模式

  1. 构造器私有化,防止外部new对象
  2. 类的内部创建对象
  3. 向外暴露一个静态公共方法获取实例

饿汉模式1(静态常量)代码如下
优点:代码简单,类装载的时候完成单例对象的创建。不存在线程同步安全问题
缺点:在类装载的时候完成实例化,没有达到懒加载的效果,创建的对象如果自始至终没有使用,会造成内存的浪费
package com.hy.singlePattern;
/**

  • @author hanyong

  • @date 2020/5/12 23:07
    */
    public class SingleE1 {

    private SingleE1(){ }

    private static SingleE1 instance=new SingleE1();

    public static SingleE1 getInstance(){
    return instance;
    }
    }
    饿汉模式2(静态代码块)代码如下
    本质同上面一样,都是装载类的时候创建实例,优缺点也是一样
    package com.hy.singlePattern;

/**

  • @author hanyong

  • @date 2020/5/12 23:24
    */
    public class SingleE2 {

    private static SingleE2 instance;
    private SingleE2(){}
    static {
    instance=new SingleE2();
    }
    public static SingleE2 getInstance(){
    return instance;
    }
    }

2)懒汉模式
懒汉模式1,线程不安全 代码如下
优缺点:起到懒加载效果,及就是调用才创建,但是只能满足单线程使用,多线程场景会有问题
当有一个线程if(null==instance)满足这个条件走到if里面但是还没有创建对象,另一个线程也判断满足条件走进创建的代码。则会产生多个实例。(不推荐使用)
package com.hy.singlePattern;

/**

  • @author hanyong
  • @date 2020/5/12 23:32
    */
    public class SingleL1 {
    private SingleL1(){};
    private static SingleL1 instance;
    public static SingleL1 getInstance(){
    if(null==instance){
    instance=new SingleL1();
    }
    return instance;
    }
    }

懒汉模式2 synchronized方法枷锁保证线程安全 代码如下
优缺点:解决线程安全,效率太低,每个线程想要获得类的实例时执行 getInstance方法都会进行同步。(不推荐使用)
package com.hy.singlePattern;

/**

  • @author hanyong
  • @date 2020/5/12 23:43
    */
    public class SingleL2 {
    private SingleL2(){};
    private static SingleL2 instance;
    public static synchronized SingleL2 getInstance(){
    if(instance==null){
    instance=new SingleL2();
    }
    return instance;
    }
    }

懒汉模式3 synchronized代码块保证线程安全 代码如下
缺点:对上面的改进,想着同步产生实例化,但是线程不安全,当有一个判断if(instance==null)满足后还未来的季执行,下一个线程也进行了判断满足条件。则会创建多个实例。所有这种方式是错误的。不能使用
package com.hy.singlePattern;
/**

  • @author hanyong
  • @date 2020/5/12 23:52
    */
    public class SingleL3 {
    private SingleL3(){};
    private static SingleL3 instance;
    public static SingleL3 getInstance(){
    if(instance==null){
    synchronized (SingleL3.class){
    instance=new SingleL3();
    }
    }
    return instance;
    }
    }

懒汉模式4 双重检查保障线程安全 代码如下
优缺点:双重检查,进行两次判断,保证线程安全;实例化代码只执行一次。当后面进入创建实例方法时判断instance不为null直接return
代码效率高,线程安全。推荐使用
package com.hy.singlePattern;
/**

  • @author hanyong
  • @date 2020/5/13 0:01
    */
    public class SingleL4 {
    private SingleL4(){};
    private volatile static SingleL4 instance;
    public static SingleL4 getInstance(){
    if(instancenull){
    synchronized (SingleL4.class){
    if(instance
    null){
    instance=new SingleL4();
    }
    }
    }
    return instance;
    }
    }

懒汉模式5 静态内部类应用实例 代码如下
优缺点:采用类装载的机制来保证初始化实例时只有一个线程;静态内部类方式在SingleL5 类装载时并不会立即实例化,而是在被需要的时候才会进行实例化,也就时调用getInstance的时候才会装载SingleL5Instance类,再进行实例化SingleL5 。这样实现了懒加载; 类的静态属性只会在第一次加载的时候初始化,所以jvm确保了线程安全。线程安全,效率高推荐使用
package com.hy.singlePattern;
/**

  • @author hanyong
  • @date 2020/5/13 0:07
    */
    public class SingleL5 {
    private SingleL5(){}
    private static class SingleL5Instance{
    private final static SingleL5 INSTANCE=new SingleL5();
    }
    public static SingleL5 getInstance(){
    return SingleL5Instance.INSTANCE;
    }
    }

懒汉模式6 枚举方式实现 代码如下
优缺点:避免多线程问题,还能防止反序列化重新创建新的对象。推荐使用
package com.hy.singlePattern;

/**

  • @author hanyong

  • @date 2020/5/13 0:22
    */
    public class SingleL6Test {

    public static void main(String[] args) {
    SingleL6 in1=SingleL6.INSTANCE;
    SingleL6 in2=SingleL6.INSTANCE;
    System.out.println(in1==in2);
    in1.test();
    }
    }
    enum SingleL6{
    INSTANCE;
    public void test(){
    System.out.println(“whh”);
    }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值