设计模式-创建型模式-单例模式

单例模式(Singleton)

保证一个类的实例在特定范围只有一份(例如一个JVM内部,一个线程内部),并且提供全局访问点可以访问到这份实例。

应用场景

  1. Spring(Singleton作用域的Bean对象,Spring只是把对象存放于map容器,并提供了一个访问点)
  2. Mybatis(ErrorContext对象是每个线程一份此类实例)
  3. Class对象
  4. 常量池。。。(线程池、连接池都可以设计为单例)

对象分析

  1. 具体产品对象(例如Singleton)
    在这里插入图片描述

应用分析

  1. 优势:科学使用资源,避免频繁创建、销毁对象时造成的资源浪费
  2. 劣势:设计不够严谨会存在线程安全问题,可扩展性相对较差

举个栗子

class Singleton01 {//此设计在多线程环境中存在不安全
    private Singleton01(){}
    private static Singleton01 instance;
    public static Singleton01 getInstance() {
        if (instance == null) {
            instance = new Singleton01();
        }
        return instance;
    }
}
class Singleton02 {
    private Singleton02(){}
    private static Singleton02 instance;
    //场景:大对象,稀少用,频繁访问会导致大量阻塞
    public static synchronized Singleton02 getInstance() {
        if (instance == null) {
            instance = new Singleton02();
        }//对象创建:延迟创建,按需加载,延迟加载
        return instance;
    }
}
class Singleton03 {//特点同Singleton02,jdk8之前同步代码块比同步方法性能好一些
    private Singleton03(){}
    private static Singleton03 instance;
    public static  Singleton03 getInstance() {
        synchronized(Singleton03.class) {
            if (instance == null) {
                instance = new Singleton03();
            }
        }
        return instance;
    }
}
class Singleton04 {
    private Singleton04(){}
    /**
     * 当有一个变量是多线程共享访问时,而且我们要保证变量的安全性,尽量使用volatile修饰
     * 双重检查机制通常会用到volatile
     * volatile:JMM(需要了解JMM)
     *
     * 1)保证可见性(一个线程修改结束,其他线程可见)
     * 2)禁止指令重排序
     * 3)但是不能保证原子性,所以一般用于修饰变量
     *
     * instance=new Singleton();
     * a)堆内存开辟空间
     * b)对象属性初始化
     * c)执行构造方法
     * d)为变量instance赋值
     * JVM可能会优化执行过程,导致指令重排序:比如b、d可能会颠倒顺序
     */
    private static volatile Singleton04 instance;
    /**
     * 基于Singleton03进行优化
     * 1)尽量减少阻塞的线程
     * 2)尽量缩小锁的应用范围(锁的代码块)
     */
    public static  Singleton04 getInstance() {
        if(instance == null) {//双重验证。
            synchronized (Singleton04.class) {
                if (instance == null) {
                    instance = new Singleton04();
                }
            }
        }//大对象,稀少用
        return instance;
    }
}
class Singleton05 {
    //private int[] array=new int[4096*1024];
    /**
     * 类加载时创建(实时加载)
     */
    private static Singleton05 instance=
            new Singleton05();
    private Singleton05(){}
    //适合小对象,频繁访问
    //大对象容易内存溢出
    public static  Singleton05 getInstance() {
        return instance;
    }
    //Singleton05.show();
    //public static void show(){}
}
class Singleton06 {
    //private int[] array=new int[4096*1024];
    /**
     * 基于内部类实现对象的延迟加载策略
     */
    static class Inner {
        private static Singleton06 instance =
                new Singleton06();
    }
    private Singleton06(){}
    //适合大对象,频繁访问
    public static  Singleton06 getInstance() {
        return Inner.instance;
    }
    //Singleton05.show();
    //public static void show(){}
}

/**
 * 枚举类型:基于枚举类型创建单例对象
 */
enum Singleton07{//Singleton07.class
    instance;//此实例在类加载时创建
    //Singleton07.instance输出instance名字,因为调用了toString方法
    private Singleton07(){}
}
public class Demo {
    public static void main(String[] args) {
//        System.out.println(Singleton01.getInstance());
//        System.out.println(Singleton01.getInstance());
//        System.out.println(Singleton01.getInstance());
        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new Thread() {
                @Override
                public void run() {
                    System.out.println(Singleton01.getInstance());
                }
            });
        }
        for (Thread thread : list) {
            thread.start();
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值