关闭

[置顶] 单例模式成型版

标签: 单例模式
706人阅读 评论(0) 收藏 举报
分类:

单例模式可以说是最容易理解的模式了,也是应用最广的模式之一,先看看定义吧。


定义

确保单例类只有一个实例,并且这个单例类提供一个函数接口让其他类获取到这个唯一的实例。

什么时候需要使用单例模式呢:如果某个类,创建时需要消耗很多资源,即new出这个类的代价很大;或者是这个类占用很多内存,如果创建太多这个类实例会导致内存占用太多。

关于单例模式,虽然很简单,无需过多的解释,但是这里还要提个醒,其实单例模式里面有很多坑。我们去会会单例模式。最简单的单例模式如下:

public class TestSingle {

    private static TestSingle instance = null;

    private TestSingle(){}

    public static TestSingle getInstance(){
        if (instance== null){
            instance = new TestSingle();
        }
        return instance;
    }

}
如果是单线程下的系统,这么写肯定没问题。可是如果是多线程环境呢?这代码明显不是线程安全的,存在隐患:某个线程拿到的instance可能是null,可能你会想,这有什么难得,直接在getInstance()函数上加sychronized关键字不就好了。可是你想过没有,每次调用getInstance()时都要执行同步,这带来没必要的性能上的消耗。注意,在方法上加sychronized关键字时,一个线程访问这个方法时,其他线程无法同时访问这个类其他sychronized方法。的我们看看另外一种实现:

public class TestSingle {

    private static TestSingle instance = null;

    private TestSingle() {
    }

    public static TestSingle getInstance() {
        if (instance == null) {
            synchronized (TestSingle.class) {
                if (instance == null) {
                    instance = new TestSingle();
                }
            }
        }
        return instance;
    }

}

为什么需要2次判断是否为空呢?第一次判断是为了避免不必要的同步,第二次判断是确保在此之前没有其他线程进入到sychronized块创建了新实例。这段代码看上去非常完美,但是,,,却有隐患!问题出现在哪呢?主要是在instance=new Singleton();这段代码上。这段代码会编译成多条指令,大致上做了3件事:

(1)给Singleton实例分配内存
(2)调用Singleton()构造函数,初始化成员字段
(3)将instance对象指向分配的内存(此时instance就不是null啦~)

上面的(2)和(3)的顺序无法得到保证的,也就是说,JVM可能先初始化实例字段再把instance指向具体的内存实例,也可能先把instance指向内存实例再对实例进行初始化成员字段。考虑这种情况:一开始,第一个线程执行instance=new Singleton();这句时,JVM先指向一个堆地址,而此时,又来了一个线程2,它发现instance不是null,就直接拿去用了,但是堆里面对单例对象的初始化并没有完成,最终出现错误~ 。

看看另外一种方式:


public class TestSingle {

    private volatile static TestSingle instance = null;

    private TestSingle() {
    }

    public static TestSingle getInstance() {
        if (instance == null) {
            synchronized (TestSingle.class) {
                if (instance == null) {
                    instance = new TestSingle();
                }
            }
        }
        return instance;
    }

}

相比前面的代码,这里只是对instance变量加了一个volatile关键字volatile关键字的作用是:线程每次使用到被volatile关键字修饰的变量时,都会去堆里拿最新的数据。换句话说,就是每次使用instance时,保证了instance是最新的。注意:volatile关键字并不能解决并发的问题,关于volatile请查看其它相关文章。但是volatile能解决我们这里的问题。




































1
0
查看评论

Maya: 菜单 曲面 >双轨成形>双轨成形2工具

曲面 >双轨成形>双轨成形2工具 可以沿着两条路径线在两条轮廓线之间生成一个曲面。
  • u011275873
  • u011275873
  • 2013-08-05 20:27
  • 1064

基带传输与成形滤波

平方根升余弦滤波器 1.Rcosfir:design a raisedcosine FIR filter.(rcosfir是低通滤波用的,以便后面加载频。)       B= RCOSFIR(R, N_T, RATE, T) designs and ret...
  • wordwarwordwar
  • wordwarwordwar
  • 2017-01-27 19:42
  • 3735

【转自知乎】5G关键技术之波束成形

偶然读到知乎上的一个文章,关于[波束成形]概念,写的很通俗易懂,也有较强抛砖引玉的效果。 故在这里转载分享。 链接:https://zhuanlan.zhihu.com/p/21800662 转载正文如下: 5G关键技术之波束成型 原作者:李一雷 · 2016年8月...
  • szzjlzy
  • szzjlzy
  • 2016-12-19 18:34
  • 6582

Maya: 菜单 曲面 >双轨成形>双轨成形3+工具

曲面 >双轨成形>双轨成形3+工具 可以通过两条路径曲线和多条轮廓曲线来生成曲面。
  • u011275873
  • u011275873
  • 2013-08-05 20:28
  • 1542

高分子材料成型工艺(一)

第〇章 绪论 ##### 高分子材料的历史 (10min) graph LR A[天然高分子直接利用]---B[皮毛 \核桃壳 秸秆];A-->C C[天然高分子化学改性]---D[橡胶硫化\纤维素合成];C-->E E[高分子合成]---F[合成树脂];E-->G G[高...
  • libido001
  • libido001
  • 2017-02-20 10:34
  • 272

对单例模式的优化

(1)从线程安全性上讲,不加同步的懒汉式是线程不安全的,比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,那就可能导致并发问题。如下示例: public static Singleton getInstance(){ if(instance == n...
  • sinat_23224827
  • sinat_23224827
  • 2015-09-16 22:31
  • 598

MATLAB脉冲成型

Fs=8; Delay=3; R=0.5; [yf,tf]=rcosine(Fd,Fs,'fir',R,Delay); figure(1) plot(yf); grid; xlabel('Time'); ylabel('Amplitude...
  • yuan1164345228
  • yuan1164345228
  • 2015-05-22 17:02
  • 1528

MATLAB信号处理仿真-基带脉冲成形的数字滤波器

http://bbs.ednchina.com/BLOG_ARTICLE_3008491.HTM 本次我们探讨另外一个在本科阶段让我们头痛的东西,通信原理之必考曲目,拼死也要背下来的内容,基带脉冲成形。然而俺对这个东西的理解和认识却是在本科以后的事情。 早年(比如[黑][社][会]大佬用摩托罗...
  • yuan1164345228
  • yuan1164345228
  • 2016-02-27 21:40
  • 2053

高分子材料成型(十)

第十章 二次成型 一次成型 二次成型 第一节 二次成型原理 聚合物的物理状态 玻璃态、类橡胶态、粘流态 结晶材料/非晶材料 聚合物的粘弹形变 聚合物加工的总形变 = 普弹形变 + 高弹形变 + 粘性形变 r=rE+rH+rV=σE1+σE2(1−e−E2η2t)+ση3tr=r_E+r_H+r_...
  • libido001
  • libido001
  • 2017-05-31 20:09
  • 89

成形滤波器和匹配滤波器

为了消除码间串扰,根据奈奎斯特第一准则,分析用平方根升余弦滚降滤波器来想实现无码间干扰。 以下摘自通信原理--樊昌信--P151 该理想滤波器,物理不可实现,还需要寻找另外的设计----- 为了解决理想低通特性存在的问题,可以使理想低通滤波特性的边沿缓慢下降,这成为"滚...
  • weiweiliulu
  • weiweiliulu
  • 2017-07-31 10:36
  • 431
    个人资料
    • 访问:28879次
    • 积分:1250
    • 等级:
    • 排名:千里之外
    • 原创:83篇
    • 转载:1篇
    • 译文:0篇
    • 评论:20条
    最新评论