單例模式是指對一個對象進行一次實例化,而後全局均可以調用該實例化對象來完成項目的開發。java
在計算機系統中,線程池、緩存、日誌對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應用都或多或少具備資源管理器的功能。每臺計算機能夠有若干個打印機,但只能有一個Printer Spooler,以免兩個打印做業同時輸出到打印機中。每臺計算機能夠有若干通訊端口,系統應當集中管理這些通訊端口,以免一個通訊端口同時被兩個請求同時調用。總之,選擇單例模式就是爲了不不一致狀態,避免政出多頭。緩存
餓漢式單例是指在方法調用前,實例就已經建立好了。下面是實現代碼:安全
package com.thread.singleton;
/** * 單例模式-- 餓漢式 * Created by Fant.J. * 2018/2/25 19:24 */
public class Singleton1 {
/** 私有化構造方法,在外部不能實例化對象 */
private Singleton1(){}
/** 在這裏實例化 靜態對象 (優勢:不存在線程安全問題。 缺點:每次調用都實例化,佔用空間) */
private static Singleton1 singleton1 = new Singleton1();
public static Singleton1 getInstance(){
return singleton1;
}
}
複製代碼
優勢:不存在線程安全問題。 缺點:每次調用都實例化,佔用空間jvm
懶漢式單例是指在方法調用獲取實例時才建立實例,由於相對餓漢式顯得「不急迫」,因此被叫作「懶漢模式」。
下面是實現代碼:性能
package com.thread.singleton;
/** * 單例模式 -- 懶漢式 * Created by Fant.J. * 2018/2/25 19:30 */
public class Singleton2 {
private Singleton2(){}
private static Singleton2 instance;
public synchronized static Singleton2 getInstance() {
/* 下面這段代碼 不是原子性操做 會出現線程安全問題 。**/
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
複製代碼
在這段代碼中,在if語句裏面,就可能跑有多個線程同步判斷和同步new。會產生線程安全問題。優化
雖然2方法解決了性能問題, 可是還會有問題 。spa
問題來自 jvm 的優化:指令重排序(有興趣瞭解),咱們能夠在對象中添加volatile 關鍵字來 不讓jvm對該 對象作優化
完善後的代碼以下:線程
package com.thread.singleton;
/** * 單例模式 -- 懶漢式 * Created by Fant.J. * 2018/2/25 19:30 */
public class Singleton2 {
private Singleton2(){}
private static Singleton2 instance;
public synchronized static Singleton2 getInstance() {
/* 下面這段代碼 不是原子性操做 會出現線程安全問題 。 解決方法:1.給方法加上synchronized(變成單線程,影響性能) 2.給代碼塊加synchronized(雙重檢查加鎖) 雖然2方法解決了性能問題, 可是還會有問題 。 問題來自 jvm 的優化:指令重排序(有興趣瞭解) 咱們能夠在對象中添加volatile 關鍵字來 不讓jvm對該 對象作優化 **/
if (instance == null) {
synchronized (Singleton2.class){
if (instance == null){
instance = new Singleton2();
}
}
}
return instance;
}
}複製代碼
你們以爲不錯能夠點個贊在關注下,之後還會分享更多文章!設計