单件模式

单件模式确保一个类只有一个实例,并提供一个全局访问点。
把某个类设计成自己管理的一个单独实例,同时也避免其他类再自行产生实例。要想取得单件实例,通过单件类是唯一的途径。

一个经典的单件模式(延迟实例化)

public class Singleton {
    private static Singleton uniqueSingleton;
    //申明私有的构造器
    private Singleton(){}

    //获得实例
    public static Singleton getInstance(){
        if(uniqueSingleton==null){
            uniqueSingleton=new Singleton();
        }
        return uniqueSingleton;
    }
}

当需要实例时,向类查询,它会返回单个实例。如果不需要这个实例,那它就永远不会产生。这就是延迟实例化。

但是,在多线程中,这样的延迟实例化会出现问题:
这里写图片描述

针对这个问题,可以有三种处理办法
1、把getInstance()方法变成同步的方法。迫使每个线程在进入到这个方法之前,要先等别的线程离开该方法。不会有两个线程可以同时进入这个方法。

public class Singleton {
    private static Singleton uniqueSingleton;
    //申明私有的构造器
    private Singleton(){}

    //获得实例
    public static synchronized Singleton getInstance(){
        if(uniqueSingleton==null){
            uniqueSingleton=new Singleton();
        }
        return uniqueSingleton;
    }
}

但是,只有第一次执行此方法时,才需要同步,一旦设置好uniqueInstance变量,就不再需要同步这个方法。而之后每次调用这个方法,同步都是一种累赘。同步一个方法可能造成程序执行效率下降。

2、不使用延迟实例化,而是在加载这个类时马上创建此唯一的单件实例:

public class Singleton {
//在静态初始化器中创建单件,保证任何线程访问静态变量之前,都先创建此实例
   private static Singleton uniqueSingleton=new Singleton();
    //申明私有的构造器
    private Singleton(){}

    //获得实例
    public static  Singleton getInstance(){
        return uniqueSingleton;
    }
}

3、使用“双重检查加锁”的方式,在getInstance()中减少使用同步
利用双重检查加锁,首先检查是否实例已经创建,如果尚未创建,才进行同步,这样,只有第一次会同步。

public class Singleton {
    //volatile关键词确保,当uniqueSingleton变量被初始化成singleton实例时,
    //多个线程正确的处理uniqueSingleton变量
    private volatile static Singleton uniqueSingleton;
    //申明私有的构造器
    private Singleton(){}

    //获得实例
    public static  Singleton getInstance(){
        if(uniqueSingleton==null){
            synchronized (Singleton.class){
                if(uniqueSingleton==null){
                    uniqueSingleton=new Singleton();
                }
            }
        }

        return uniqueSingleton;
    }
}

每个类加载器都定义了一个命名空间,如果有两个以上的类加载器,不同的类加载器可能会加载同一个类。这时使用单件模式,需自行指定类加载器,并指定同一个类加载器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值