本文主要是介绍单实例的写法最保险的写法应采用静态方式的预生成 ,不要用双重检查的懒汉模式等,JDK1.6之后加了volatile也要谨慎,需要考证是否解决这个问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
单实例的写法最保险的写法应采用静态方式的预生成 ,不要用双重检查的懒汉模式等,JDK1.6之后加了volatile也需要考证是否解决了这个问题
推荐写法案例一
/*以单例模式启动*/
private PendingJobPool() {}
private static class JobPoolHolder{
public static PendingJobPool pool = new PendingJobPool();
}
public static PendingJobPool getInstance() {
return JobPoolHolder.pool;
}
推荐的写法 清单10
class Singleton
{
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();
private Singleton()
{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
{
return instance;
}
}
清单 10 的代码也没有使用同步如果您的目标是消除同步,则这将是一个很好的选择。
方法二
貌似现在可以用volatile了。 因为java的内存模式也在改进中。Doug Lea 在他的文章中写道:“根据最新的 JSR133 的 Java 内存模型,如果将引用类型声明为 volatile,双重检查模式就可以工作了”,参见 http://gee.cs.oswego.edu/dl/cpj/updates.html
实际分析如下也不可以,既使加了volatile,在堆上new对象时候,同样存在重排序的情况,(MARK老师,enjoyedu .Lesson14)
所以下面的说法也是待考证的,不可以轻信
lz提到的双重检测的问题是因为instruction reorder的关系导致在//3时: instance=new Singleton (); 这句假设分为三步 1.先申请内存 2.构造Singleton 3.将instance指向新的内存区域 如果不进行指令重排,这个是没问题的. 如果指令重排后执行顺序是. 1 3 2. 这就导致执行3后,instance已经非null, 此时若恰好有别的线程重新访问get_instance函数.将得到instance非null的结果,并此时返回一个 还没执行完构造函数的instance实例.从而出错. 但是volatile关键字的第二个语义,便是‘禁止指令重排优化’. 因此,如果把instance变量声明为 volatile , 双重检测法似乎也是work的. 如下:
private static volatile Singleton instance;
public static Singleton getInstance()
{ if (instance == null) {
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
原文链接:https://blog.csdn.net/chenchaofuck1/article/details/51702129
这篇关于单实例的写法最保险的写法应采用静态方式的预生成 ,不要用双重检查的懒汉模式等,JDK1.6之后加了volatile也要谨慎,需要考证是否解决这个问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!