真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

設計模式-單例模式(一)-創(chuàng)新互聯(lián)

單例模式
  • 一 官方定義
  • 二 單例模式八種方式
    • 2.1 餓漢式(靜態(tài)常量)
      • 代碼案例
      • 案例分析
    • 2.2 餓漢式(靜態(tài)代碼塊)
      • 代碼案例
      • 案例分析
    • 2.3 懶漢式(線程不安全)
      • 代碼案例
      • 案例分析
    • 2.4 懶漢式(線程安全,同步方法)
      • 代碼案例
      • 案例分析
    • 2.5 懶漢式(線程不安全,同步代碼塊)
      • 代碼案例
      • 案例分析
    • 2.6 雙重檢查 (推薦使用)
      • 代碼案例
      • 案例分析
        • 優(yōu)點
        • 可能出現(xiàn)的問題
        • 擴展 - Volatile
    • 2.7 靜態(tài)內(nèi)部類 (推薦使用)
      • 代碼案例
      • 案例分析
    • 2.8 枚舉方式
      • 代碼案例
      • 案例分析
    • 三 注意事項
    • 四 單例模式的使用場景

創(chuàng)新互聯(lián)建站專業(yè)網(wǎng)站制作、網(wǎng)站設計,集網(wǎng)站策劃、網(wǎng)站設計、網(wǎng)站制作于一體,網(wǎng)站seo、網(wǎng)站優(yōu)化、網(wǎng)站營銷、軟文推廣等專業(yè)人才根據(jù)搜索規(guī)律編程設計,讓網(wǎng)站在運行后,在搜索中有好的表現(xiàn),專業(yè)設計制作為您帶來效益的網(wǎng)站!讓網(wǎng)站建設為您創(chuàng)造效益。一 官方定義

所謂類的單例設計模式,就是采取一定的方法保證在整個的軟件系統(tǒng)中,對某個類只能存在一個對象實例,并且該類只提供一個取得其對象實例的方法(靜態(tài)方法)

Spring 中的 bean 默認都是單例模式,每個bean定義只生成一個對象實例,每次 getBean請求獲得的都是此實例

二 單例模式八種方式

單例模式的八種實現(xiàn)方式,如下所示

  • 餓漢式(靜態(tài)常量)
  • 餓漢式(靜態(tài)代碼塊)
  • 懶漢式(線程不安全)
  • 懶漢式(線程安全,同步方法)
  • 懶漢式(線程安全,同步代碼塊)
  • 雙重檢查
  • 靜態(tài)內(nèi)部類
  • 枚舉方式
2.1 餓漢式(靜態(tài)常量) 代碼案例
class Singleton {//一:構造器的私有化    防止外部用構造器...
    private Singleton() {}

    //二:類的內(nèi)部創(chuàng)建對象    final static
    private static final Singleton singleton = new Singleton();

    //三:對外提供公共的靜態(tài)方法    返回該類唯一的對象實例
    public static Singleton getInstance() {return singleton;
    }
}
案例分析
//案例演示 - 餓漢式
public class SingletonDemo {public static void main(String[] args) {//      方式一:靜態(tài)常量
        Singleton instance = Singleton.getInstance();
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance == instance1); //true
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
}

在這里插入圖片描述
通過結果可以發(fā)現(xiàn)返回的是同一個對象所以單例模式是實現(xiàn)的。

寫法分析
優(yōu)勢: 簡單 避免多線程的同步問題
劣勢: 沒有達到懶加載的效果 內(nèi)存的浪費

2.2 餓漢式(靜態(tài)代碼塊) 代碼案例
//方式二:靜態(tài)代碼塊的方式
class Singleton {//構造器私有化
    private Singleton() {}

    //類的內(nèi)部創(chuàng)建對象
    private static final Singleton singleton;

    static {singleton = new Singleton();
    }

    //對外提供公共的靜態(tài)的方法
    public static Singleton getInstance() {return singleton;
    }
}
案例分析

優(yōu)勢: 簡單 避免多線程的同步問題
劣勢: 沒有達到懶加載的效果 內(nèi)存的浪費

2.3 懶漢式(線程不安全) 代碼案例
class Singleton{//構造器私有化
    private Singleton(){}

    //類的內(nèi)部提供對象
    private static Singleton singleton;

    //對外提供公共的靜態(tài)方法的時候,來判斷
    public static Singleton getInstance(){if (singleton == null){singleton = new Singleton();
        }

        return singleton;
    }

}
案例分析

優(yōu)勢:起到了懶加載的效果 不會造成內(nèi)存浪費

在使用到的時候才會創(chuàng)建對象。判斷有無對象,有則返回,無創(chuàng)建后再返回

劣勢:只能在單線程下使用,多線程情況下線程不安全 不推薦這種方式的
在這里插入圖片描述

① 在多線程的情況下,有一個對象進入if判斷通過,還沒執(zhí)行到創(chuàng)建對象這一步驟時
② 有另外一個對象也進入了if判斷,也通過了。
此時就會出現(xiàn)多個實例,造成線程不安全。

2.4 懶漢式(線程安全,同步方法)

在獲取對象的靜態(tài)方法上添加 synchronized 關鍵字,實現(xiàn)同步方法。解決線程不安全問題。

代碼案例
//加入同步處理  同步方法
class Singleton{//構造器私有化
    private Singleton(){}

    //類的內(nèi)部提供對象
    private static Singleton singleton;

    //對外提供公共的靜態(tài)方法的時候,來判斷
    public static synchronized Singleton getInstance(){if (singleton == null){singleton = new Singleton();
        }

        return singleton;
    }

}
案例分析

解決了線程安全問題,但是效率太低

每一個線程需求拿實例的時候都要在外面等候另一線程處理完

2.5 懶漢式(線程不安全,同步代碼塊)

將實例化對象過程放入同步代碼塊中

代碼案例
//加入同步處理 - 同步代碼塊的方式  不推薦的
class Singleton{//構造器私有化
    private Singleton(){}

    //類的內(nèi)部提供對象
    private static Singleton singleton;

    //對外提供公共的靜態(tài)方法的時候,來判斷
    public static Singleton getInstance(){if (singleton == null){synchronized (Singleton.class){singleton = new Singleton();
            }

        }

        return singleton;
    }

}
案例分析

不推薦的,解決不了線程的安全問題

這種方式本意是想解決同步方法的問題。但是我們分析一下。在多線程情況下還是有可能創(chuàng)建多個實例的問題。

2.6 雙重檢查 (推薦使用) 代碼案例
class Singleton{private Singleton(){}
    //禁止指令重排
    private static volatile Singleton singleton;
    //加入雙重檢查機制
    public static Singleton getInstance(){if (singleton == null){synchronized (Singleton.class){if (singleton == null){singleton = new Singleton();
                }
            }
        }

        return singleton;
    }
}
案例分析 優(yōu)點

線程安全

解決了線程安全問題
① 多線程時,若兩個線程同時滿足第一層非空判斷,等待調(diào)用同步代碼塊。
② 由于添加了synchronized ,當?shù)谝粋€線程進來時,發(fā)現(xiàn)Singleton對象為空,進行創(chuàng)建對象并返回。
③ 當另外一個線程調(diào)用同步代碼塊時,進行再次對象非空判斷,發(fā)現(xiàn)對象已經(jīng)創(chuàng)建成功。不在執(zhí)行創(chuàng)建對象流程,返回已有對象

懶加載

使用到對象時才創(chuàng)建,不會造成內(nèi)存的浪費

效率很高

先進性了singleton 是否為空的判斷,singleton 如果不為空直接返回結果。倘若無第一層判空,多線程時每次都要進行synchronized 等待其他線程處理結束,才能進入內(nèi)部非空判斷,效率相對低。

可能出現(xiàn)的問題

我們認為的 new Singleton() 操作

1)分配內(nèi)存地址 M
2)在內(nèi)存 M 上初始化Singleton 對象
3)將M的地址賦值給 instance 對象

JVM編譯優(yōu)化后(指令重排)可能的 new Singleton() 操作

1)分配內(nèi)存地址 M
2)將M的地址賦值給instance變量
3)在內(nèi)存M上初始化 Singleton 對象

這就有可能出現(xiàn)空指針異常
異常發(fā)生過程
在這里插入圖片描述
解決方式:關鍵字 Volatile 來禁止指令重排

擴展 - Volatile

輕量級的同步機制 (低配版) 沒有保證原子性
三大特性
保證可見性
其中一個線程修改了主內(nèi)存共享變量的值,要寫回主內(nèi)存,并要及時通知其他線程可見
沒有保證原子性
沒法(不能保證)不可分割,完整,要么同時成功,要么同時失敗
禁止指令重排
和底層內(nèi)存屏障相關 避免多線程下出現(xiàn)指令亂序的情況

擴展-線程切換

Java的一條語句對應的cpu指令可能是多條,其中任意一條cpu指令在執(zhí)行完都可能發(fā)生線程切換
count += 1,對應cpu 指令如下:

1)將變量count從內(nèi)存加載到cpu寄存器
2)寄存器中 +1
3)將結果寫入內(nèi)存(緩存機制寫入的可能是cpu而不是內(nèi)存)
在這里插入圖片描述

2.7 靜態(tài)內(nèi)部類 (推薦使用) 代碼案例
class Singleton{private Singleton(){}

    private static class SingletonInstance{public static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(){return SingletonInstance.INSTANCE;
    }
}
案例分析

①當Singleton類加載時,靜態(tài)內(nèi)部類是不會加載的。
②只有調(diào)用getInstance方法用到了SingletonInstance.INSTANCE靜態(tài)變量時導致SingletonInstance靜態(tài)內(nèi)部類進行加載。

不會出現(xiàn)線程安全問題
JVM來幫我們保證了線程的安全性
利用靜態(tài)內(nèi)部類的特點,效率也很高,實際開發(fā)中推薦使用的

2.8 枚舉方式 代碼案例
public class EnumDemo {public static void main(String[] args) {//驗證其正確性
        Singleton instance = Singleton.INSTANCE;
        Singleton instance1 = Singleton.INSTANCE;
        System.out.println(instance == instance1); //true
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());

    }
}

enum Singleton{INSTANCE; //屬性
}
案例分析

不僅可以避免線程安全問題 還可以防止反序列化重新創(chuàng)建對象。推薦使用

三 注意事項
  1. 單例模式保證了系統(tǒng)內(nèi)存中該類只存在一個對象,節(jié)省了系統(tǒng)資源,對于一些需要頻繁創(chuàng)建銷毀的對象,使用單例模式可以提高系統(tǒng)性能
  2. 當想實例化一個單例類的時候,必須要記住使用相應的獲取對象的方法,而不是使用 new
四 單例模式的使用場景
  • 對于一些需要頻繁創(chuàng)建銷毀的對象
  • 重量級的對象(創(chuàng)建對象時耗時過多,或者耗費資源過多)
  • 經(jīng)常使用到的對象
  • 工具類對象
  • 數(shù)據(jù)源,session。。。。

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)站名稱:設計模式-單例模式(一)-創(chuàng)新互聯(lián)
分享鏈接:http://weahome.cn/article/djdeec.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部