- 單例設(shè)計模式- 餓漢式
public class Singleton1 {
// 隨著類的加載就已經(jīng)new了對象
private static Singleton1 mInstance = new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance() {
return mInstance;
}
}
- 單例設(shè)計模式 - 懶漢式
/**
* @Description 單例設(shè)計模式 - 懶漢式
*/
public class Singleton2 {
// 使用的時候才會去new對象充包,可能更加高效
// 會有問題?多線程并發(fā)的問題,如果多個線程調(diào)用會有多個實例
private static Singleton2 mInstance;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (mInstance == null) {
mInstance = new Singleton2();
}
return mInstance;
}
}
- 單例設(shè)計模式 - 懶漢式 - 多線程并發(fā)
/**
* @Description 單例設(shè)計模式 - 懶漢式 - 多線程并發(fā)
*/
public class Singleton3 {
// 使用的時候才會去new對象,可能更加高效
// 會有問題?多線程并發(fā)的問題抛杨,如果多個線程調(diào)用會有多個實例 如何解決
private static Singleton3 mInstance;
private Singleton3() {
}
// 同步鎖,解決了線程安全的問題。但是會出現(xiàn)效率的問題剂癌?
// 效率比較低,每次獲取都要經(jīng)過同步鎖的判斷 看 Singleton4
public static synchronized Singleton3 getInstance() {
if (mInstance == null) {
mInstance = new Singleton3();
}
return mInstance;
}
}
- 單例設(shè)計模式 - 懶漢式 - 多線程并發(fā) 雙重檢測 (同步鎖DCL) (常用)
/**
* @Description 單例設(shè)計模式 - 懶漢式 - 多線程并發(fā) 雙重檢測 (同步鎖DCL)
*/
public class Singleton4 {
// 使用的時候才會去new對象惭等,可能更加高效
// 會有問題珍手?多線程并發(fā)的問題,如果多個線程調(diào)用會有多個實例 如何解決
// 添加 volatile 的用處是什么辞做?
// 1. 防止重排序
// 2. 線程可見性-某一個線程改了公用對象(變量)琳要,短時間內(nèi)另一個線程可能是不可見的,因為每一個線程都有自己的緩存區(qū)(線程工作區(qū))
private static volatile Singleton4 mInstance;
private Singleton4() {
}
// Singleton4 mInstance = new Singleton4();
// 1. 開辟一塊空間(內(nèi)存)
// 2. 初始化對象
// 3. 給變量賦值(指向內(nèi)存地址)
// 但是 2 和 3 在java多線程順序是不固定的 volatile 為了防止 2和3互換位置
// 1. 開辟一塊空間(內(nèi)存)
// 2. 給變量賦值(指向內(nèi)存地址)
// 3. 初始化對象
// 同步鎖秤茅,解決了線程安全的問題稚补。但是會出現(xiàn)效率的問題?
// 既保證線程安全同時效率比較高
// 這種方式還是會有問題的框喳? 用 volatile 解決
public static Singleton4 getInstance() {
if (mInstance == null) {
synchronized (Singleton4.class) {
if (mInstance == null) {
mInstance = new Singleton4();
}
}
}
return mInstance;
}
}
- 單例設(shè)計模式 - 靜態(tài)內(nèi)部類(常用)
/**
* @Description 單例設(shè)計模式 - 靜態(tài)內(nèi)部類(比較常用)
*/
public class Singleton5 {
private Singleton5() {
}
private static class Singleton5Inner {
public static volatile Singleton5 mInstance = new Singleton5();
}
public static Singleton5 getInstance() {
return Singleton5Inner.mInstance;
}
}
- 單例設(shè)計模式 - 枚舉
/**
* @Description 枚舉單例模式
*/
enum class SingleTonEnum {
INSTANCE;
fun doSomething() {
println("do some thing")
}
}
- 單例設(shè)計模式 - 容器管理 - Android源碼 SystemServiceRegistry 獲取系統(tǒng)的服務(wù)
/**
* @Description 單例設(shè)計模式 - 容器管理 - SystemServiceRegistry 獲取系統(tǒng)的服務(wù)
*/
public class Singleton7 {
private static Map<String, Object> mSingleMap = new HashMap<>();
static {
mSingleMap.put("activity_manager", new Singleton7());
}
private Singleton7() {}
public static Object getService(String serviceName) {
return mSingleMap.get(serviceName);
}
}
- 單例設(shè)計模式 - 自己寫
/**
* @Description 單例設(shè)計模式
*/
public class Singleton8 {
private static Singleton8 mInstance;
static {
mInstance = new Singleton8();
}
private Singleton8() {}
public static Singleton8 getInstance() {
return mInstance;
}
}
- volatile關(guān)鍵字
- 防止重排序
- 線程可見性-某一個線程改了公用對象(變量)课幕,短時間內(nèi)另一個線程可能是不可見的厦坛,因為每一個線程都有自己的緩存區(qū)(線程工作區(qū))
- 測試volatile
public class VolatileTest {
public static void main(String[] args) {
ThreadRun threadRun = new ThreadRun();
new Thread(threadRun).start();
while (true) {
if (threadRun.isFlag()) {
System.out.println("--------跳出循環(huán)------");
break;
}
}
// 沒有個 flag 設(shè)置 Volatile 結(jié)果一直是 flag true 不會執(zhí)行 --------跳出循環(huán)------
}
static class ThreadRun implements Runnable {
private volatile boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println(" flag " + isFlag());
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
}
注意
- 自己學習,不為盈利
- 如有侵權(quán)乍惊,可以聯(lián)系刪除