我是皇帝我獨苗之單例模式
阿新 • • 發佈:2018-10-09
tro [] print 解決辦法 cto ini random 分析 day 什麽是單例模式?
?
確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。通俗一點就是確保一個類只能產生一個對象,所有對象對他的依賴都是相同的。
?
單例模式的幾種實現方式
?
?
確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。通俗一點就是確保一個類只能產生一個對象,所有對象對他的依賴都是相同的。
?
單例模式的幾種實現方式
?
-
懶漢式(線程不安全)
?public class Singleton { private static Singleton singleton; private Singleton (){} public static synchronized Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
- 餓漢式(線程安全)
?public class Singleton { private static Singleton singleton = new Singleton(); private Singleton (){} public static Singleton getInstance() { return singleton; } }
單例模式的註意事項
?
高並發的情況下註意單例模式的線程同步問題,測試代碼如下:
?
public class Emperor { private static String name = null; private static Emperor emperor = null; //限制產生多個對象 private Emperor(String e) { Emperor.name=e; } //通過該方法獲得實例對象 public static Emperor getInstance(String e) { if (emperor == null) { emperor = new Emperor(e); } return emperor; } //類中的其他方法盡量使用static public static void say(String m) { // Emperor.name=e; System.out.println("我是:"+ m +", 參見皇帝"+Emperor.name); } }
?
package com.zgz.dm.Singleton; public class Minister { public static void main(String[] args) { Minister1 minister1 = new Minister1(); Minister2 minister2 = new Minister2(); new Thread(minister1).start(); new Thread(minister2).start(); /*for(int day=0; day<3; day++) { Emperor emperor = Emperor.getInstance(); emperor.say(); }*/ } } class Minister1 implements Runnable{ private String minister = "王安石"; private String s = "宋神宗1"; @Override public void run() { for(int i=0; i<10; i++) { Emperor emperor = Emperor.getInstance(); emperor.say(s,minister); try { Thread.sleep((int)Math.random()*200); } catch (Exception e) { e.printStackTrace(); } } } } class Minister2 implements Runnable{ private String minister = "蘇軾"; private String s = "宋神宗2"; @Override public void run() { for(int i=0; i<10; i++) { Emperor emperor = Emperor.getInstance(); emperor.say(s,minister); try { Thread.sleep((int)Math.random()*1000); } catch (Exception e) { e.printStackTrace(); } } } }
?
測試結果:
?
?
原因分析:
?
王安石應該是宋神宗1啊?為啥是宋神宗12呢,就說明內存中存在兩個對象。一個線程A執行到 emperor = new Emperor(),但還沒有獲得對象(對象的初始化需要時間),第二個線程B正在執行,執行到 (emperor == null),線程B獲得判斷條件為真,於是繼續執行。於是A與B都獲得了對象,內存中出現了兩個對象。
?
解決辦法:
?
加鎖,執行效率低。建議使用餓漢式單例
我是皇帝我獨苗之單例模式