64. System.out.println(singleton.hashCode());
65. }
66. public static void main(String[] args)
67. {
68. Thread threads[] = new Thread;
69. for (int i = 0; i < threads.length; i++)
70. threads[i] = new MyThread();
71. for (int i = 0; i < threads.length; i++)
72. threads[i].start();
73. }
74.}
在上面的代碼調(diào)用yield方法是為了使單件模式的線程不安全性表現(xiàn)出來,如果將這行去掉,上面的實現(xiàn)仍然是線程不安全的,只是出現(xiàn)的可能性小得多。
程序的運行結(jié)果如下:
25358555
26399554
7051261
29855319
5383406
上面的運行結(jié)果可能在不同的運行環(huán)境上有所有同,但一般這五行輸出不會完全相同。從這個輸出結(jié)果可以看出,通過getInstance方法得到的對象實例是五個,而不是我們期望的一個。這是因為當(dāng)一個線程執(zhí)行了Thread.yield()后,就將CPU資源交給了另外一個線程。由于在線程之間切換時并未執(zhí)行到創(chuàng)建Singleton對象實例的語句,因此,這幾個線程都通過了if判斷,所以,就會產(chǎn)生了建立五個對象實例的情況(可能創(chuàng)建的是四個或三個對象實例,這取決于有多少個線程在創(chuàng)建Singleton對象之前通過了if判斷,每次運行時可能結(jié)果會不一樣)。
要想使上面的單件模式變成線程安全的,只要為getInstance加上synchronized關(guān)鍵字即可。代碼如下
75.public static synchronized Singleton getInstance() { }
當(dāng)然,還有更簡單的方法,就是在定義Singleton變量時就建立Singleton對象,代碼如下
76.private static final Singleton sample = new Singleton();
然后在getInstance方法中直接將sample返回即可。這種方式雖然簡單,但不知在getInstance方法中創(chuàng)建Singleton對象靈活。讀者可以根據(jù)具體的需求選擇使用不同的方法來實現(xiàn)單件模式。
相關(guān)推薦:
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |