第二個(gè)單例代碼不嚴(yán)謹(jǐn),可能會(huì)創(chuàng)建出多個(gè)實(shí)例。比如有兩個(gè)線程同時(shí)訪問getInstance(),當(dāng)?shù)谝粋€(gè)線程進(jìn)入synchronized塊但還沒有new的時(shí)候,第二個(gè)線程也走到if處,這個(gè)時(shí)候uniqueInstance
創(chuàng)新互聯(lián)建站2013年開創(chuàng)至今,先為句容等服務(wù)建站,句容等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為句容企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
=null,if返回true,第二個(gè)線程就進(jìn)入了if塊,但在synchronized塊外面等待,然后第一個(gè)線程創(chuàng)建實(shí)例,第二個(gè)線程也能成功創(chuàng)建實(shí)例。
不知道我說得夠不夠清楚。你可以看看《effective
Java》這本書,里面有專門講到這個(gè)問題。
一、懶漢式單例\x0d\x0a在類加載的時(shí)候不創(chuàng)建單例實(shí)例。只有在第一次請(qǐng)求實(shí)例的時(shí)候的時(shí)候創(chuàng)建,并且只在第一次創(chuàng)建后,以后不再創(chuàng)建該類的實(shí)例。\x0d\x0a \x0d\x0apublic class LazySingleton {\x0d\x0a /**\x0d\x0a * 私有靜態(tài)對(duì)象,加載時(shí)候不做初始化\x0d\x0a */\x0d\x0a private static LazySingleton m_intance=null;\x0d\x0a /**\x0d\x0a * 私有構(gòu)造方法,避免外部創(chuàng)建實(shí)例\x0d\x0a */\x0d\x0a private LazySingleton(){\x0d\x0a }\x0d\x0a /**\x0d\x0a * 靜態(tài)工廠方法,返回此類的唯一實(shí)例. \x0d\x0a * 當(dāng)發(fā)現(xiàn)實(shí)例沒有初始化的時(shí)候,才初始化.\x0d\x0a */\x0d\x0a synchronized public static LazySingleton getInstance(){\x0d\x0a if(m_intance==null){\x0d\x0a m_intance=new LazySingleton();\x0d\x0a }\x0d\x0a return m_intance;\x0d\x0a }\x0d\x0a}\x0d\x0a\x0d\x0a二、餓漢式單例\x0d\x0a在類被加載的時(shí)候,唯一實(shí)例已經(jīng)被創(chuàng)建。\x0d\x0a \x0d\x0apublic class EagerSingleton {\x0d\x0a /**\x0d\x0a * 私有的(private)唯一(static final)實(shí)例成員,在類加載的時(shí)候就創(chuàng)建好了單例對(duì)象\x0d\x0a */\x0d\x0a private static final EagerSingleton m_instance = new EagerSingleton();\x0d\x0a /**\x0d\x0a * 私有構(gòu)造方法,避免外部創(chuàng)建實(shí)例\x0d\x0a */\x0d\x0a private EagerSingleton() {\x0d\x0a }\x0d\x0a /**\x0d\x0a * 靜態(tài)工廠方法,返回此類的唯一實(shí)例.\x0d\x0a * @return EagerSingleton\x0d\x0a */\x0d\x0a public static EagerSingleton getInstance() {\x0d\x0a return m_instance;\x0d\x0a }\x0d\x0a}\x0d\x0a \x0d\x0a************************************************************************************** 懶漢方式,指全局的單例實(shí)例在第一次被使用時(shí)構(gòu)建; \x0d\x0a餓漢方式,指全局的單例實(shí)例在類裝載時(shí)構(gòu)建 \x0d\x0a**************************************************************************************\x0d\x0a\x0d\x0a三、登記式單例\x0d\x0a這個(gè)單例實(shí)際上維護(hù)的是一組單例類的實(shí)例,將這些實(shí)例存放在一個(gè)Map(登記薄)中,對(duì)于已經(jīng)登記過的實(shí)例,則從工廠直接返回,對(duì)于沒有登記的,則先登記,而后返回。\x0d\x0apublic class RegSingleton {\x0d\x0a /**\x0d\x0a * 登記薄,用來存放所有登記的實(shí)例\x0d\x0a */\x0d\x0a private static Map m_registry = new HashMap();\x0d\x0a //在類加載的時(shí)候添加一個(gè)實(shí)例到登記薄\x0d\x0a static {\x0d\x0a RegSingleton x = new RegSingleton();\x0d\x0a m_registry.put(x.getClass().getName(), x);\x0d\x0a }\x0d\x0a /**\x0d\x0a * 受保護(hù)的默認(rèn)構(gòu)造方法\x0d\x0a */\x0d\x0a protected RegSingleton() {\x0d\x0a }\x0d\x0a /**\x0d\x0a * 靜態(tài)工廠方法,返回指定登記對(duì)象的唯一實(shí)例;\x0d\x0a * 對(duì)于已登記的直接取出返回,對(duì)于還未登記的,先登記,然后取出返回\x0d\x0a * @param name\x0d\x0a * @return RegSingleton\x0d\x0a */\x0d\x0a public static RegSingleton getInstance(String name) {\x0d\x0a if (name == null) {\x0d\x0a name = "RegSingleton";\x0d\x0a }\x0d\x0a if (m_registry.get(name) == null) {\x0d\x0a try {\x0d\x0a m_registry.put(name, (RegSingleton) Class.forName(name).newInstance());\x0d\x0a } catch (InstantiationException e) {\x0d\x0a e.printStackTrace();\x0d\x0a } catch (IllegalAccessException e) {\x0d\x0a e.printStackTrace();\x0d\x0a } catch (ClassNotFoundException e) {\x0d\x0a e.printStackTrace();\x0d\x0a }\x0d\x0a }\x0d\x0a return m_registry.get(name);\x0d\x0a }\x0d\x0a /**\x0d\x0a * 一個(gè)示意性的商業(yè)方法\x0d\x0a * @return String\x0d\x0a */\x0d\x0a public String about() {\x0d\x0a return "Hello,I am RegSingleton!";\x0d\x0a }\x0d\x0a}
單例模式(Singleton) ,屬于最常見的設(shè)計(jì)模式之一,大部分系統(tǒng)都會(huì)用到,目的是為了維護(hù)系統(tǒng)中唯一的一個(gè)實(shí)例。
可分為eager模式,示例代碼如下:
Java代碼
1.class EagerSingleton{
2. private static final EagerSingleton m_instance = new EagerSingleton();
3. private EagerSingleton(){}
4. public static EagerSingleton getInstance(){
5. return m_instance;
6. }
7.}
class EagerSingleton{
private static final EagerSingleton m_instance = new EagerSingleton();
private EagerSingleton(){}
public static EagerSingleton getInstance(){
return m_instance;
}
}
和 lazy模式,示例代碼如下:
Java代碼
1.class LazySingleton{
2. private static LazySingleton m_instance = null;
3. private LazySingleton(){}
4. public synchronized static getInstance(){
5. if(m_instance == null){
6. m_instance = new LazySingleton();
7. }
8. return m_instance;
9. }
10.}
class LazySingleton{
private static LazySingleton m_instance = null;
private LazySingleton(){}
public synchronized static getInstance(){
if(m_instance == null){
m_instance = new LazySingleton();
}
return m_instance;
}
}
java源碼中,Runtime.getRuntime()就是單例的一個(gè)例子。
單例模式的精神就是整個(gè)系統(tǒng)中維護(hù)一個(gè)實(shí)例,推廣開來,如果在一個(gè)系統(tǒng)中需要維護(hù)多個(gè)示例,那么就產(chǎn)生了多例模式(multiton)。
多例模式(Multiton) ,通過聚集對(duì)象了保留自身的多個(gè)示例,根據(jù)客戶端的參數(shù)返回所需要的實(shí)例。
示例代碼如下:
Java代碼
1.class Multiton{
2. private final int INSTANCE_SIZE = 10;
3. private static Map instances = new HashMap(INSTANCE_SIZE);
4. private String name;
5. private Multiton(){}
6. private Multiton(String name){
7. this.name = name;
8. }
9. public synchronized static getInstance(String name){
10. if(instances.containsKey(name)){
11. return instances.get(name);
12. }
13. else{
14. ins = new Multiton(name);
15. instances.put(name, ins);
16. return ins;
17. }
18. }
19.}
class Multiton{
private final int INSTANCE_SIZE = 10;
private static Map instances = new HashMap(INSTANCE_SIZE);
private String name;
private Multiton(){}
private Multiton(String name){
this.name = name;
}
public synchronized static getInstance(String name){
if(instances.containsKey(name)){
return instances.get(name);
}
else{
ins = new Multiton(name);
instances.put(name, ins);
return ins;
}
}
}
[nextpage]
一個(gè)實(shí)用的例子就是KeyGenerator, 示例代碼如下:
Java代碼
1.class KeyGenerator{
2. private final int POOL_SIZE = 20;
3. private static Map instances = new HashMap(16);
4. private KeyInfo keyinfo;
5. private KeyGenerator(){}
6. private KeyGenerator(String keyName){
7. this.keyinfo = new KeyInfo(POOL_SIZE, keyName);
8. }
9. public synchronized static getInstance(String keyName){
10. if(instances.containsKey(keyName)){
11. return (KeyGenerator)instances.get(keyName);
12. }
13. else{
14. keyGen = new KeyGenerator(keyName);
15. instances.put(name, keyGen);
16. return keyGen;
17. }
18. }
19. public synzhronized int getNextKey(){
20. return keyinfo.getNextKey();
21. }
22. }
class KeyGenerator{
private final int POOL_SIZE = 20;
private static Map instances = new HashMap(16);
private KeyInfo keyinfo;
private KeyGenerator(){}
private KeyGenerator(String keyName){
this.keyinfo = new KeyInfo(POOL_SIZE, keyName);
}
public synchronized static getInstance(String keyName){
if(instances.containsKey(keyName)){
return (KeyGenerator)instances.get(keyName);
}
else{
keyGen = new KeyGenerator(keyName);
instances.put(name, keyGen);
return keyGen;
}
}
public synzhronized int getNextKey(){
return keyinfo.getNextKey();
}
}
單例模式大致有五種寫法,分別為懶漢,惡漢,靜態(tài)內(nèi)部類,枚舉和雙重校驗(yàn)鎖。
1、懶漢寫法,常用寫法
class?LazySingleton{
private?static?LazySingleton?singleton;
private?LazySingleton(){
}
public?static?LazySingleton?getInstance(){
if(singleton==null){
singleton=new?LazySingleton();
}
return?singleton;
}???
}
2、惡漢寫法,缺點(diǎn)是沒有達(dá)到lazy loading的效果
class?HungrySingleton{
private?static?HungrySingleton?singleton=new?HungrySingleton();
private?HungrySingleton(){}
public?static?HungrySingleton?getInstance(){
return?singleton;
}
}
3、靜態(tài)內(nèi)部類,優(yōu)點(diǎn):加載時(shí)不會(huì)初始化靜態(tài)變量INSTANCE,因?yàn)闆]有主動(dòng)使用,達(dá)到Lazy loading
class?InternalSingleton{
private?static?class?SingletonHolder{
private?final?static??InternalSingleton?INSTANCE=new?InternalSingleton();
}???
private?InternalSingleton(){}
public?static?InternalSingleton?getInstance(){
return?SingletonHolder.INSTANCE;
}
}
4、枚舉,優(yōu)點(diǎn):不僅能避免多線程同步問題,而且還能防止反序列化重新創(chuàng)建新的對(duì)象
enum?EnumSingleton{
INSTANCE;
public?void?doSomeThing(){
}
}
5、雙重校驗(yàn)鎖,在當(dāng)前的內(nèi)存模型中無效
class?LockSingleton{
private?volatile?static?LockSingleton?singleton;
private?LockSingleton(){}
//詳見:
public?static?LockSingleton?getInstance(){
if(singleton==null){
synchronized(LockSingleton.class){
if(singleton==null){
singleton=new?LockSingleton();
}
}
}
return?singleton;
}
}
參考自:
單例模式:就是一個(gè)類僅創(chuàng)建一個(gè)對(duì)象;pre t="code" l="java"public class Singleton {
private static volatile Singleton singleton = null;
private Singleton(){}// 構(gòu)造方法
public static Singleton getSingleton(){// 單例模式
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
當(dāng)前標(biāo)題:java單例代碼,java的單例模式代碼
本文來源:http://m.kartarina.com/article46/hsdpeg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站導(dǎo)航、移動(dòng)網(wǎng)站建設(shè)、面包屑導(dǎo)航、自適應(yīng)網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)