单例设计模式 有更新!

  |   1 评论   |   2,528 浏览

    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

    评论

    发表评论

    validate