今天把设计模式拿出来看了下,发现以前对于单例模式的理解很是肤浅,没考虑线程安全,在考虑了线程安全的情况下又没考虑性能,当然我遇到的系统都不怎么考虑并发性能,所以其实也无所谓,当看到单例模式的时候,上网搜索了下,发下一片很好的帖子,我把其中的单例模式整理了下,给了个结果出来。
帖子地址:http://blog.csdn.net/zhangerqing/article/details/8194653
前提都是在考虑线程安全的情况下,可以有两种情况。分别是懒汉式和饿汉式的一种实现。
1.性能不太好,每次锁对象,当然如果你遇到的跟我遇到的系统都一样不考虑性能问题,其实这么做也没问题,但是不好。正如Oracle高级编程里面所说的那样,你的sql能正确的完成任务,但并不代表他能很好的完成任务。
2.我们只希望在第一次getInstance的时候去实例化对象,这个就做到了,并且线程安全,但是如果类加载的时候出问题还是有可能出问题,所以借用那篇帖子里说的,要完成完美的实现是不可能的,我们只能根据实际情况来选择合适的方式。
1.直接锁整个对象,保证线程安全,但是由于每次获取都会锁对象,性能不好,也不是我们希望的。
package singlePattern; /** * Thread safe single pattern, but performance is poor, because every time we will lock the instance, * we hope lock the instance on first time but all times * * @author Administrator * */ public class SinglePattern { // private instance private static SinglePattern instance = null; // private constructor private SinglePattern() { } // public getInstance method public synchronized static SinglePattern getInstance() { if (instance == null) { instance = new SinglePattern(); } return instance; } }
2.我们需要的情形是在第一次初始化需要同步,之后的调用就不需要考虑线程同步。由于JVM在加载类的时候是互斥的,我们知道类加载器在加载类的时候会直接把静态变量和静态代码块执行一次,然后再去去调用普通代码快,然后去调用构造方法初始化堆,然后在返回引用赋值给栈里面的引用。于是我们可以利用类加载的静态变量和静态代码块来安全的构造单例实例。
package singlePattern; /** * Thread safe and performance good. * @author Administrator * */ public class UserSinglePattern { // private constructor private UserSinglePattern() {} // static inner class, for create a single pattern instance private static class NewInstance { private static UserSinglePattern instance = new UserSinglePattern(); } // the get method for single pattern instance public static UserSinglePattern getInstance() { return NewInstance.instance; } }
再贴下我参考的地址对作者表示感谢:http://blog.csdn.net/zhangerqing/article/details/8194653