您当前的位置: 首页 > 

java持续实践

暂无认证

  • 3浏览

    0关注

    746博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式 单例模式

java持续实践 发布时间:2022-03-20 13:03:40 ,浏览量:3

文章目录
      • 单例模式介绍
      • 单例模式的7种写法
        • 0. 静态类的使用
        • 懒汉模式 线程不安全的写法
        • 线程安全的懒汉模式 方法上全局加锁
        • 饿汉式单例模式
        • 单例模式 内部类的写法 线程安全 (推荐)
        • 双重检查的单例模式 (推荐)
        • cas 加 AtomicReference 实现安全的单例
        • 枚举实现单例模式

单例模式介绍

系统中只允许创建一个对象.

  1. 数据库的连接池.
  2. spring的单例bean
  3. 配置类等
单例模式的7种写法 0. 静态类的使用
public class Singleton00 {

    /**
     * 系统第一次运行的时候, 直接初始化该类 , 不需要维持任何状态,  仅仅需要全局访问.
     */
    public static Map cache = new ConcurrentHashMap();
}

系统第一次运行的时候, 直接初始化该类 , 不需要维持任何状态, 仅仅需要全局访问

懒汉模式 线程不安全的写法
public class Singleton01 {

    private static Singleton01 instance;

    // 构造方法私有化, 防止外部创建对象
    private Singleton01() {
    }

    public static Singleton01 getInstance() {
        // 多线程的情况下会创建多个对象
        if (instance != null) {
            return instance;
        }
        return new Singleton01();
    }
}
线程安全的懒汉模式 方法上全局加锁
public class Singleton02 {

    private static Singleton02 instance;

    private Singleton02() {
    }

    // 全局加锁 线程安全但 性能差.
    public static synchronized Singleton02 getInstance() {
        if (null != instance) return instance;
        return new Singleton02();
    }
}
饿汉式单例模式
public class Singleton03 {
    // 程序一运行就加载单例对象, 虽然线程安全, 但会导致内存暴增
    private static Singleton03 instance = new Singleton03();

    private Singleton03() {
    }

    public static Singleton03 getInstance() {
        return instance;
    }
}
单例模式 内部类的写法 线程安全 (推荐)
public class Singleton04 {

    private static class SingletonHolder {
        // 一个类的构造方法在多线程环境下是线程安全的 jvm可以保证多线程并发访问的准确性
        private static Singleton04 instance = new Singleton04();
    }
    private Singleton04() {
    }

    public static Singleton04 getInstance() {
        return SingletonHolder.instance;
    }

}
双重检查的单例模式 (推荐)

教程中 volatile 没有加上. 此处volatile 保证可见性, 并且保证创建对象的时候 禁止指令重排.

public class Singleton05 {

    private volatile static Singleton05 instance;

    private Singleton05() {
    }

    public static Singleton05 getInstance() {
        if (null!=instance) return instance;
        synchronized (Singleton05.class) {
            if (null == instance) {
                instance = new Singleton05();
            }
        }
        return instance;
    }
}
cas 加 AtomicReference 实现安全的单例

AtomicReference 可以封装引⽤⼀个V实例,⽀持并发访问如上的单例⽅式就是使⽤了这样的⼀个特点。 CAS有⼀个缺点就是盲等,如果⼀直没有获取到对象将会处于死循环中

public class Singleton06 {
    private static final AtomicReference INSTANCE = new AtomicReference();

    private static Singleton06 instance;

    private Singleton06() {
    }

    public static final Singleton06 getInstance() {
        // CAS有⼀个缺点就是盲等,如果⼀直没有获取到对象将会处于死循环中
        for (; ; ) {
            Singleton06 instance = INSTANCE.get();
            if (instance!=null) return instance;
            // 只有是null 的时候 才创建对象 .
            INSTANCE.compareAndSet(null, new Singleton06());
            return INSTANCE.get();
        }
    }
}
枚举实现单例模式
/**
 * 类名称:Singleton07
 * 枚举实现单例模式  此种⽅式在存在继承场景下是不可⽤的
 *  创建时间:2022/3/19 17:48
 */
public enum Singleton07 {

    INSTANCE;

    public void test() {
        System.out.println("hi singleton");
    }
}

测试类

import com.thc.design.Singleton03;
import com.thc.design.Singleton04;
import com.thc.design.Singleton05;
import com.thc.design.Singleton07;
import org.junit.Test;

/**
 * 类名称:SingletonTest
 * 创建时间:2022/3/19 17:27
 */
public class SingletonTest {

    @Test
    public void test_Singleton03() {
        Singleton03 instance1 = Singleton03.getInstance();
        Singleton03 instance2 = Singleton03.getInstance();

        System.out.println(instance1); // Singleton03@722c41f4
        System.out.println(instance2); // Singleton03@722c41f4
    }

    @Test
    public void test_Singleton04() {
        Singleton04 instance1 = Singleton04.getInstance();
        Singleton04 instance2 = Singleton04.getInstance();

        System.out.println(instance1); // Singleton04@722c41f4
        System.out.println(instance2); // Singleton04@722c41f4
    }

    @Test
    public void test_Singleton05() {
        Singleton05 instance1 = Singleton05.getInstance();
        Singleton05 instance2 = Singleton05.getInstance();

        System.out.println(instance1); // Singleton05@722c41f4
        System.out.println(instance2); // Singleton05@722c41f4
    }

    @Test
    public void test_Singleton07() {
        Singleton07.INSTANCE.test(); //hi singleton
    }

}
关注
打赏
1658054974
查看更多评论
立即登录/注册

微信扫码登录

0.0402s