完美的单例模式创建
今天把設計模式拿出來看了下,發(fā)現(xiàn)以前對于單例模式的理解很是膚淺,沒考慮線程安全,在考慮了線程安全的情況下又沒考慮性能,當然我遇到的系統(tǒng)都不怎么考慮并發(fā)性能,所以其實也無所謂,當看到單例模式的時候,上網(wǎng)搜索了下,發(fā)下一片很好的帖子,我把其中的單例模式整理了下,給了個結果出來。
帖子地址:http://blog.csdn.net/zhangerqing/article/details/8194653
前提都是在考慮線程安全的情況下,可以有兩種情況。分別是懶漢式和餓漢式的一種實現(xiàn)。
1.性能不太好,每次鎖對象,當然如果你遇到的跟我遇到的系統(tǒng)都一樣不考慮性能問題,其實這么做也沒問題,但是不好。正如Oracle高級編程里面所說的那樣,你的sql能正確的完成任務,但并不代表他能很好的完成任務。
2.我們只希望在第一次getInstance的時候去實例化對象,這個就做到了,并且線程安全,但是如果類加載的時候出問題還是有可能出問題,所以借用那篇帖子里說的,要完成完美的實現(xiàn)是不可能的,我們只能根據(jù)實際情況來選擇合適的方式。
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 instanceprivate static SinglePattern instance = null;// private constructorprivate SinglePattern() {}// public getInstance methodpublic synchronized static SinglePattern getInstance() {if (instance == null) {instance = new SinglePattern();}return instance;} }2.我們需要的情形是在第一次初始化需要同步,之后的調用就不需要考慮線程同步。由于JVM在加載類的時候是互斥的,我們知道類加載器在加載類的時候會直接把靜態(tài)變量和靜態(tài)代碼塊執(zhí)行一次,然后再去去調用普通代碼快,然后去調用構造方法初始化堆,然后在返回引用賦值給棧里面的引用。于是我們可以利用類加載的靜態(tài)變量和靜態(tài)代碼塊來安全的構造單例實例。
package singlePattern;/*** Thread safe and performance good.* @author Administrator**/ public class UserSinglePattern {// private constructorprivate UserSinglePattern() {}// static inner class, for create a single pattern instanceprivate static class NewInstance {private static UserSinglePattern instance = new UserSinglePattern();}// the get method for single pattern instancepublic static UserSinglePattern getInstance() {return NewInstance.instance;} }
3.如果實例采用靜態(tài)的就能實現(xiàn)在類加載的時候線程安全的初始化實例,但是卻不能實現(xiàn)lazy加載,而采用上面的靜態(tài)內部類的方式就能實現(xiàn)lazy加載,因為虛擬機機制是需要調用getInstance()方法的時候才會加載靜態(tài)內部類,如果不調用那么他是不會被加載的。下面是測試代碼,同時擁有2個靜態(tài)內部類來創(chuàng)建對象,但是只調用其中一個那么就只會加載一個,另外一個是不會被加載的。
public class SinglePatternThreadSafe {// 私有構造方法private SinglePatternThreadSafe() {System.out.println(123);}private SinglePatternThreadSafe(String str) {System.out.println(321);}// 內部類,利用類加載的互斥性來達到單例的創(chuàng)建private static class NewInstance {private static SinglePatternThreadSafe instance = new SinglePatternThreadSafe();}private static class NewInstance1 {private static SinglePatternThreadSafe in = new SinglePatternThreadSafe("11");}// 返回實例的公共方法public static SinglePatternThreadSafe getInstance() {return NewInstance.instance;}public static SinglePatternThreadSafe getInstance(String str) {return NewInstance1.in;}public static void main(String[] args) {SinglePatternThreadSafe.getInstance();}// 只打印出123而沒有打印11 }
再貼下我參考的地址對作者表示感謝:http://blog.csdn.net/zhangerqing/article/details/8194653
這個也寫的很好:http://www.cnblogs.com/coffee/archive/2011/12/05/inside-java-singleton.html
這篇也測試了如果在不調用靜態(tài)內部類的方法或者變量或者常量的時候內部類是不會被加載的,http://yongliang567.iteye.com/blog/904467
轉載于:https://www.cnblogs.com/dreamroute/p/3898433.html
總結
- 上一篇: Android开发——跟随手指的小球实现
- 下一篇: ActivePython2.7 +Fir