面试中经常会被问单例模式,下面就简单说下解决方案
//饿汉式
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