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)出來,如果將這行去掉,上面的實(shí)現(xiàn)仍然是線程不安全的,只是出現(xiàn)的可能性小得多。
程序的運(yùn)行結(jié)果如下:
25358555
26399554
7051261
29855319
5383406
上面的運(yùn)行結(jié)果可能在不同的運(yùn)行環(huán)境上有所有同,但一般這五行輸出不會(huì)完全相同。從這個(gè)輸出結(jié)果可以看出,通過getInstance方法得到的對(duì)象實(shí)例是五個(gè),而不是我們期望的一個(gè)。這是因?yàn)楫?dāng)一個(gè)線程執(zhí)行了Thread.yield()后,就將CPU資源交給了另外一個(gè)線程。由于在線程之間切換時(shí)并未執(zhí)行到創(chuàng)建Singleton對(duì)象實(shí)例的語句,因此,這幾個(gè)線程都通過了if判斷,所以,就會(huì)產(chǎn)生了建立五個(gè)對(duì)象實(shí)例的情況(可能創(chuàng)建的是四個(gè)或三個(gè)對(duì)象實(shí)例,這取決于有多少個(gè)線程在創(chuàng)建Singleton對(duì)象之前通過了if判斷,每次運(yùn)行時(shí)可能結(jié)果會(huì)不一樣)。
要想使上面的單件模式變成線程安全的,只要為getInstance加上synchronized關(guān)鍵字即可。代碼如下
75.public static synchronized Singleton getInstance() { }
當(dāng)然,還有更簡(jiǎn)單的方法,就是在定義Singleton變量時(shí)就建立Singleton對(duì)象,代碼如下
76.private static final Singleton sample = new Singleton();
然后在getInstance方法中直接將sample返回即可。這種方式雖然簡(jiǎn)單,但不知在getInstance方法中創(chuàng)建Singleton對(duì)象靈活。讀者可以根據(jù)具體的需求選擇使用不同的方法來實(shí)現(xiàn)單件模式。
相關(guān)推薦:
各地2012年計(jì)算機(jī)等級(jí)考試費(fèi)用匯總
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |