JAVA 单件模式详解

    我们在JAVA开发过程中经常会用到线程池、缓存、注册表对象、日志对象等对象。这些对象往往只能有一个实例,如果出现多个上述对象的实例,可能会导致很多问题。

    当然我们可以定义全局变量,全局变量会在程序一开始就创建好对象,如果该对象在程序执行过程中对资源消耗非常大而且使用率不高,在面对对性能要求高的系统中就成为了累赘。所以我们才需要用到单件模式进行对象创建。


public class SingleClass{
    //创建一个静态私有的SingleClass实例成为唯一实例
    private static SingleClass Instance;
    //私有化SingleClass类构造器
    private SingleClss(){}
    //采用getInstance方法实例化对象并返回
        public static SingleClass getInstance(){
    //判断实例是否为空保证只有一个实例产生
            if(Instance == null){
                Instance = new SingleClass();
            }
                return Instance;
        }
}

这样我们就完成了一个简单的单件模式实现。

多线程编程是java开发中经常使用到的。在多线程环境下,上述的单件模型可能就会出现严重的问题。这是因为JVM中多线程执行顺序导致的。如下:

线程一线程二Instance
public static SingleClass getInstance(){ null
 public static SingleClass getInstance(){null
if(Instance == null){ null
 if(Instance == null){null

Instance =

new SingleClass();

 return Instance;

 object1
 

Instance = 

new SingleClass();

return Instance;

object2

 

多线程模式下我们的单件实例产生了两个对象,有违我们单件模式的初衷。我们可以靠以下方式解决多线程下的单件多对象问题:

(1)将getInstance()加同步关键字synchronized

public static synchronized SingleClass getInstance(){
    if(Instance == null){
        Instance = new SingleClass();
    }
}

如果该程序调用getInstance()非常频繁,则同步方法会造成较大的运行负担,降低运行效率。所以需要考虑别的方法

(2)不再延迟实例化

public class SingleClass{
    private static SingleClass Instance = new SingleClass();

    private SingleClass();

    public static SingleClass getInstance(){
        return Instance;
    }
}

这样在线程一的一开始就为静态变量Instance创建了SingleClass实例,下面的getInstance()方法直接返回此实例,多线程中就不会产生出现两个对象实例的情况。

(3)volatile 关键字

使用volatile关键字 当Instance 被初始化的时候,多线程可以正确处理Instance变量。

volatile 的特性

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(实现可见性)
  • 禁止进行指令重排序。(实现有序性)
  • volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。
public class SingleClass{
    private volatile static SingleClass Instance;

    private SingleClass(){}
    //volatile 检查不存在实例后才进入下方同步区块
    public static SingleClass getInstance(){
        //只有第一次创建实例执行以下代码
        if(Instance == null){
            synchronized (SingleClass.class){
                if(Instance == null){
                    Instance = new SingleClass();
                }
            }
        }
        return Instance;
    }

这种做法可以优化性能,减少频繁synchronized的时间开销。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值