单例设计模式 有更新!
public class Singleton {
private static Singleton instance = null;// 在内部产生本类的实例化对象
public static Singleton getInstance() { // 通过静态方法返回instance对象
if(instance == null ){
synchronized (Singleton.class) { //使用synchronized关键字,多线程使用的时候,创建对象的时候需要加锁,性能有一定的提升(不需要多线程,那自然就无所谓了.)
instance = new Singleton();
System.out.println("重新分配");
}
}
return instance;
}
private Singleton() { // 将构造方法封装为私有化
}
public void print() {
System.out.println("Hello World!!!");
}
}
测试下↓
public class SingletonDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Singleton s1 = null;//声明对象
Singleton s2 = null;
Singleton s3 = null;
s1 = Singleton.getInstance();//取得实例化对象
s2 = Singleton.getInstance();
s3 = Singleton.getInstance();
s1.print();//调用方法
s2.print();
s3.print();
}
}
注:
将synchronized关键字加在了内部,也就是说当调用的时候是不需要加锁的,只有在instance为null,并创建对象的时候才需要加锁,性能有一定的提升。但是,这样的情况,还是有可能有问题的,看下面的情况:在Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就可能出错了,我们以A、B两个线程为例:
a>A、B线程同时进入了第一个if判断
b>A首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();
c>由于JVM内部的优化机制,JVM先画出了一些分配给Singleton实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块。
d>B进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序。
e>此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。
所以程序还是有可能发生错误,其实程序在运行过程是很复杂的,从这点我们就可以看出,尤其是在写多线程环境下的程序更有难度,有挑战性。
转载于http://blog.csdn.net/zhangerqing
评论
发表评论
|
|
此篇文章不够完美,请跳转↓
传送门:
http://tonfay.cn/articles/2019/08/06/1565086071946.html