在java中,單例有很多種寫法,面試時(shí),手寫代碼環(huán)節(jié),除了寫算法題,有時(shí)候也會(huì)讓手寫單例模式,這里記錄一下單例的幾種寫法和優(yōu)缺點(diǎn)。
1.初級(jí)寫法
2.加鎖
3.餓漢式
4.懶漢式
5.雙鎖檢驗(yàn)
6.內(nèi)部類
1.初級(jí)寫法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.java4all.test6; /** * author: yunqing * date: 2018/8/13 * description:單例模式 -- 初級(jí) */ public class singleton { private static singleton singleton = null ; public singleton() { } /**并發(fā)下會(huì)產(chǎn)生多個(gè)實(shí)例*/ public static singleton getinstance(){ if (singleton == null ){ singleton = new singleton(); } return singleton; } } |
上面這種寫法,在并發(fā)環(huán)境下,會(huì)出現(xiàn)多個(gè)實(shí)例。
2.加鎖
我們優(yōu)化上面的代碼,遇到并發(fā),很容易想到加鎖,把獲取對(duì)象的方法加上關(guān)鍵字synchronized,很巧,這種寫法也稱為懶漢式單例 ,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.java4all.test6; /** * author: yunqing * date: 2018/8/13 * description: */ public class badsynchronizedsingleton { private static badsynchronizedsingleton synchronizedsingleton; private badsynchronizedsingleton() { } /** * 缺點(diǎn):等待時(shí)間長 * 這種整個(gè)方法都同步了,效率很低 * */ public synchronized static badsynchronizedsingleton getinstance(){ if (synchronizedsingleton == null ){ synchronizedsingleton = new badsynchronizedsingleton(); } return synchronizedsingleton; } } |
但是,顯然,我們把整個(gè)方法都同步了,效率很低下,我們可以繼續(xù)優(yōu)化,只在創(chuàng)建實(shí)例的地方加上同步,參考5雙鎖檢驗(yàn)。
3.餓漢式
餓漢式的特點(diǎn)是:類在加載時(shí)就直接初始化了實(shí)例。即使沒用到,也會(huì)實(shí)例化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package com.java4all.test6; /** * author: yunqing * date: 2018/8/13 * description:餓漢式單例模式--類初始化時(shí)就自行實(shí)例化 */ public class esingleton { /**類在加載的時(shí)候直接進(jìn)行初始化*/ private static final esingleton esingleton = new esingleton(); private esingleton() {} /**對(duì)外暴露唯一接口 提供單例對(duì)象*/ public static esingleton getesingleton(){ return esingleton; } } |
4.懶漢式
懶漢式的特點(diǎn)是:用到這個(gè)實(shí)例時(shí)才去調(diào)用方法實(shí)例化。這個(gè)和2中的看起來是一樣的,因?yàn)檫@個(gè)實(shí)例化方法加了synchronized ,這樣安全一些。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.java4all.test6; /** * author: yunqing * date: 2018/8/13 * description:懶漢式單例模式 * 第一次調(diào)用時(shí)實(shí)例化 */ public class bsingleton { private static bsingleton bsingleton ; private bsingleton() { } /** * 整個(gè)方法鎖住了,效率較低 * @return */ public synchronized static bsingleton getbsingleton(){ if (bsingleton == null ){ bsingleton = new bsingleton(); } return bsingleton; } } |
5.雙鎖檢驗(yàn)
雙重非空判斷,new對(duì)象前加一次鎖。
volatile關(guān)鍵字,考慮的是,new關(guān)鍵字在虛擬機(jī)中執(zhí)行時(shí)其實(shí)分為很多步驟,具體原因可以參考深入理解java虛擬機(jī)一書(考慮的是這個(gè)new關(guān)鍵字字節(jié)碼執(zhí)行時(shí)是非原子性的),而volatile關(guān)鍵字可以防止指令重排。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.java4all.test6; /** * author: yunqing * date: 2018/8/13 * description:雙鎖檢驗(yàn) */ public class synchronizedsingleton { /**volatile防止指令重排*/ private static volatile synchronizedsingleton singleton; private synchronizedsingleton() { } /**只是在實(shí)例為空時(shí)才進(jìn)行同步創(chuàng)建 * 為什么做了2次判斷? * a線程和b線程同時(shí)進(jìn)入同步方法0 * 然后都在1位置處判斷了實(shí)例為null * 然后都進(jìn)入了同步塊2中 * 然后a線程優(yōu)先進(jìn)入了同步代碼塊2中(b線程也進(jìn)入了),然后創(chuàng)建了實(shí)例 * 此時(shí),如果沒有3處的判斷,那么a線程創(chuàng)建實(shí)例同時(shí),b線程也會(huì)創(chuàng)建一個(gè)實(shí)例 * 所以,還需要做2次判斷 * */ public static synchronizedsingleton getinstance(){ //0 if (singleton == null ){ //1 synchronized (synchronizedsingleton. class ){ //2 if (singleton == null ){ //3 singleton = new synchronizedsingleton(); //4 } } } return singleton; } } |
6.內(nèi)部類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.java4all.test6; /** * author: yunqing * date: 2018/9/15 * description:靜態(tài)內(nèi)部類 * 優(yōu)點(diǎn):1.延遲,外部類初始化時(shí)不會(huì)進(jìn)行實(shí)例創(chuàng)建,要用時(shí)才會(huì)創(chuàng)建 * 2.安全,靜態(tài)成員變量 */ public class fsingleton { private fsingleton() { } public static fsingleton getinstance(){ return singleton.fsingleton; } private static class singleton{ private static fsingleton fsingleton = new fsingleton(); } } |
總結(jié)
以上所述是小編給大家介紹的java中的6種單例寫法,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!
原文鏈接:https://blog.csdn.net/weixin_39800144/article/details/84500676