• 单例模式Singleton


    单例模式

         保证一个类只有一个实例,并且提供一个访问他的全局访问点  --《设计模式:可复用面向对象软件的基础》84页3.5节

    在某些情况下我们需要一个类在任何情况下 只需要同一个实例并且提供一个访问该实例的方法

    单例模式又分懒汉和饿汉模式

    懒汉模式:在你需要他的时候才会去创建对象,也就是你在调用访问该实例的方法的时候才会去创建


    /**
    * 单例模式 :懒汉模式
    *
    * @author 爱出走的眼睛
    *
    */
    public class Singleton {
    private static Singleton singleton;

    private Singleton() {
    System.out.println("创建对象");
    }

    public static Singleton GetInstance() {
    if (singleton==null) {
    singleton=new Singleton();
    }
    return singleton;

    }
    }

    //测试代码
    Singleton s1 = Singleton.GetInstance();
    Singleton s2 = Singleton.GetInstance();
    System.out.println(s1==s2);

    //结果为 true
    上述代码并非严格,因为没有考虑到多线程的环境下  下面我测试一下在多线程情况下出现的问题

    public class Test {
    public static void main(String[] args) {

    Thread tA = new Thread() {
    public void run() {
    Singleton.GetInstance();
    }
    };

    Thread tB = new Thread() {
    public void run() {
    Singleton.GetInstance();
    }
    };
    tA.start();
    tB.start();
    }
    }


    打印结果为:
    创建对象
    创建对象
    因为在多线程的情况下  线程A可能在创建对象之前cpu时间片用完了进入就绪状态,线程B分配到资源 这个时候由于线程A没有执行完创建对象语句,此时线程B判断依然对象为空,所以线程B也会去创建对象,这样两个线程都进入了if里面 导致单例模式失败! 

    严格的单例模式 懒汉

    /**
    * 单例模式 :严格的懒汉模式
    *
    * @author 爱出走的眼睛
    *
    */
    public class Singleton {
    //使用volatile 关键字 禁止指令排序
    private static volatile Singleton singleton;

    private Singleton() {

    }

    public static Singleton GetInstance() {
    //这里 锁代码块比锁方法更加高效
    if (singleton==null) {
    synchronized(Singleton.class) {
    if (singleton == null) {
    singleton = new Singleton();
    }
    }

    }
    return singleton;
    }
    }
    如果不懂volatile 和线程的话 需要自己补习一下同步锁和volatile 关键字

    饿汉模式: 不管你调用不调用 它都会去创建这个对象

    饿汉代码就简单很多

    public class SingletonHungry {
    //注意这里使用了final关键字
    private static final SingletonHungry singleton=new SingletonHungry();

    private SingletonHungry() {

    }

    public static SingletonHungry GetInstance(http://www.my516.com) {

    return singleton;

    }
    }
    应用场景

    最简单的一个小例子  windows系统中的任务管理器 无论你打开多少次任务管理器 他只会有一个窗口

    因为如果你打开两个任务管理器窗口 且内容一样 管理器需要去调用CPU去获取这些信息 这样设计的目的是为了减少资源浪费 所以设计成单例模式,第二点 如果你打开两个管理器发现内容不一样 这样更容易给用户带来误解。

    spring中的bean默认就是单例模式

    线程池,数据库连接池,日志对象这些也用到了单例模式
    ---------------------

  • 相关阅读:
    第五讲:深入hibernate的三种状态
    mysql安装图解 mysql图文安装教程(详细说明)
    Codeforces 13C
    ubuntu常用软件
    git安装方法
    SSH免密码登录的方法
    bash 小技巧
    Haskell 学习
    客户端connect返回错误显示No route to host
    ubuntu下C操作Mysql数据库第一步
  • 原文地址:https://www.cnblogs.com/hyhy904/p/11220044.html
Copyright © 2020-2023  润新知