单例模式

xiaoxiao2021-02-28  146

面试中经常会被问单例模式,下面就简单说下解决方案

//饿汉式 class Single { private static final Single s = new Single(); private Single(){} public static Single getInstance() { return s; } } /* 私有化构造器,是为了不让其他的类去创建对象,而其他的类需要这个对象,那就使用提供的接口getInstance()方法返回这个单例对象,那现在谈下private static final Single s = new Single();这个行代码的个人简介,私有化private,是不让其他的对象访问,静态static,只创建一次,但这个final是最难生活清楚的,常见的说法是为了不被改动(线程1在访问这个对象,而线程2去改变他,name线程1得到的结果就会出问题),但是我不理解,没有对外提供访问接口,如何能被改动?直到看到这个说法“在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。 ”,这里我才信服,final的作用,因为第一次new对象,可能回引起的问题。 */

懒汉式的单例模式

//懒汉式。 class Single { private static volatile Single s = null; private Single(){} /* 并发访问会有安全隐患,所以加入同步机制解决安全问题。 但是,同步的出现降低了效率。 可以通过双重判断的方式,解决效率问题,减少判断锁的次数。 */ public static Single getInstance() { if(s==null)/*减少判定锁的过程,这个是可以少的,存在,只是为了优化去判断锁的过程,当对象存在,直接返回,连锁都不用拿*/ { synchronized(Single.class) { if(s==null)/*实际去盘定锁是否存在,这个是必须存在,当两个线程同时到外层if中,没有这个,就会创建单例对象,违背单例的初衷*/ s = new Single(); } } return s; } } /*使用 volatile 有两个功用: 1)这个变量不会在多个线程中存在复本,直接从内存读取。 2)这个关键字会禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。 这个也就是做上面的饿汉式的final作用 但是,这个事情仅在Java 1.5版后有用,1.5版之前用这个变量也有问题,因为老版本的Java的内存模型是有缺陷的。*/

个人简介及汲取别人的优点,下面是大神的讲解http://blog.csdn.net/haoel/article/details/4028232

转载请注明原文地址: https://www.6miu.com/read-25232.html

最新回复(0)