Java中單例模式的示例分析

這篇文章主要為大家展示了“Java中單例模式的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Java中單例模式的示例分析”這篇文章吧。

創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、利津網(wǎng)絡(luò)推廣、微信小程序、利津網(wǎng)絡(luò)營銷、利津企業(yè)策劃、利津品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供利津建站搭建服務(wù),24小時(shí)服務(wù)熱線:18980820575,官方網(wǎng)址:muchs.cn

懶漢模式與餓漢模式

懶漢模式就是懶加載,用到的時(shí)候去加載,存在線程安全問題,需要手動(dòng)地加鎖控制。它的優(yōu)點(diǎn)是類加載的速度比較快,按需加載,節(jié)省資源。

餓漢模式就是在類加載的時(shí)候會(huì)創(chuàng)建出實(shí)例。它天生就不存在線程安全問題。但是類加載的速度會(huì)變慢且耗費(fèi)資源。

懶漢模式-單重檢查

示例代碼如下:

public class LazySingleton {

  private static LazySingleton singletoninstance = null;
  private Object data = new Object();

//私有化構(gòu)造方法
  private LazySingleton(){

  }
//加鎖訪問
  public static synchronized LazySingleton getInstance(){

    if(singletoninstance == null){
      singletoninstance = new LazySingleton();
    }
    return singletoninstance;
  }

  public Object getData() {
    return data;
  }

  public void setData(Object data) {
    this.data = data;
  }
}

測試代碼如下:

public class TestThread extends Thread {

  @Override
  public void run() {

    LazySingleton instance = LazySingleton.getInstance();
    System.out.println(instance.getData());
  }
}

public static void main(String[] args) {

    for(int i =0;i < 10;i++){
      TestThread t = new TestThread();
      t.start();
    }
  }
}

運(yùn)行結(jié)果如下:

java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64
java.lang.Object@306d3b64

打印出同一個(gè)object對象,表明是從同一個(gè)LazySingleton對象中獲取的數(shù)據(jù)。

但是上述代碼存在一個(gè)顯著的問題:多個(gè)線程同時(shí)訪問getInstance()方法都是排隊(duì)式的,即使該instance已經(jīng)被創(chuàng)建的情況下。然而,如果該instance已經(jīng)被創(chuàng)建,是可以支持并發(fā)訪問的。需要對鎖的控制細(xì)粒度化。

懶漢模式-雙重檢查

public class LazySingleton {
//聲明為volatile變量
  private static volatile LazySingleton singletoninstance = null;
  private Object data = new Object();

  private LazySingleton(){

  }

  public static synchronized LazySingleton getInstance(){

    if(singletoninstance == null){
      synchronized (LazySingleton.class) {
        //這個(gè)第二重的的檢查是必要的
        if(singletoninstance == null)
          singletoninstance = new LazySingleton();
      }
    }
    return singletoninstance;
  }

  public Object getData() {
    return data;
  }

  public void setData(Object data) {
    this.data = data;
  }
}

第二重檢查是為了防止:

線程A發(fā)現(xiàn)instance未被創(chuàng)建,于是申請鎖,進(jìn)入臨界區(qū)創(chuàng)建instance;于此同時(shí)另一個(gè)線程也發(fā)現(xiàn)instance未被創(chuàng)建,于是也要申請鎖去創(chuàng)建instance,問題就這樣發(fā)生了。而且,這個(gè)instance變量要被聲明為volatile,也就是其中一個(gè)線程對它就行修改之后(也就是實(shí)例化),這一修改立馬對其他線程可見,避免了無謂的等待。

檢查代碼同上,運(yùn)行結(jié)果同上。

餓漢模式

public class HungerSingleton {

  private static final HungerSingleton singletoninstance = new HungerSingleton();
  private Object data = new Object();

  private HungerSingleton(){

  }

  public static HungerSingleton getInstance(){

    return singletoninstance;
  }

  public Object getData() {
    return data;
  }

  public void setData(Object data) {
    this.data = data;
  }

}

在加載該類的時(shí)候就立馬去實(shí)例化instance,不存在線程安全問題(由jvm保證線程安全問題),但是存在資源浪費(fèi)、加載速度慢的問題。

檢查代碼同上,運(yùn)行結(jié)果同上。

Holder模式

就是利用一個(gè)靜態(tài)內(nèi)部類來實(shí)現(xiàn)instance的實(shí)例化。這里利用了靜態(tài)內(nèi)部類的一個(gè)特性:該內(nèi)部類的實(shí)例與外部類的實(shí)例 沒有綁定關(guān)系,而且只有被調(diào)用到才會(huì)裝載,從而實(shí)現(xiàn)了延遲加載

public class HolderSingleton {

  private Object data = new Object();

  private HolderSingleton(){

  }
  
  private static class InnerClass{

    private static HolderSingleton singletoninstance = new HolderSingleton();
  }

  public static HolderSingleton getInstance(){

    return InnerClass.singletoninstance;
  }

  public Object getData() {
    return data;
  }

  public void setData(Object data) {
    this.data = data;
  }
}

測試代碼同上,運(yùn)行結(jié)果同上。

在加載InnerClass的時(shí)候才會(huì)去實(shí)例化這個(gè)instance,實(shí)現(xiàn)了延遲加載,并且同餓漢模式一樣,由jvm保證線程安全。這種方法值得推薦。

應(yīng)用場景:

在整個(gè)系統(tǒng)中,只允許共用一個(gè)實(shí)例的類適合用單例模式來實(shí)現(xiàn),比如:

網(wǎng)站的計(jì)數(shù)器,只允許存在一個(gè)計(jì)數(shù)器實(shí)例;

線程池,只允許存在一個(gè)線程池對象;

連接池,只允許存在一個(gè)連接池對象;

知識(shí)點(diǎn)擴(kuò)充:

1.為什么要使用單例模式?

在我們?nèi)粘5墓ぷ髦校芏鄬ο笸ǔU加梅浅V匾南到y(tǒng)資源,比如:IO處理,數(shù)據(jù)庫操作等,那我們必須要限制這些對象只有且始終使用一個(gè)公用的實(shí)例,即單例。

2.單例模式的實(shí)現(xiàn)方式

構(gòu)造函數(shù)私有化,防止其他類生成唯一公用實(shí)例外的實(shí)例。且單例類應(yīng)該被定義為final,也就是說單例類不能被繼承,因?yàn)槿绻试S繼承那子類就都可以創(chuàng)建實(shí)例,違背了類唯一實(shí)例的初衷。

類中一個(gè)靜態(tài)變量來保存單實(shí)例的引用。

一個(gè)共有的靜態(tài)方法來獲取單實(shí)例的引用。
3.單例模式的UML類圖

Java中單例模式的示例分析

4.單例模式的經(jīng)典實(shí)現(xiàn)方式

  • 餓漢式:一開始就創(chuàng)建好實(shí)例,每次調(diào)用直接返回,經(jīng)典的“拿空間換時(shí)間”。

  • 懶漢式:延遲加載,第一次調(diào)用的時(shí)候才加載,然后返回,以后的每次的調(diào)用就直接返回。經(jīng)典“拿時(shí)間換空間”,多線程環(huán)境下要注意解決線程安全的問題。

  • 登記式:對一組單例模式進(jìn)行的維護(hù),主要是在數(shù)量上的擴(kuò)展,通過線程安全的map把單例存進(jìn)去,這樣在調(diào)用時(shí),先判斷該單例是否已經(jīng)創(chuàng)建,是的話直接返回,不是的話創(chuàng)建一個(gè)登記到map中,再返回。

以上是“Java中單例模式的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

本文標(biāo)題:Java中單例模式的示例分析
網(wǎng)站網(wǎng)址:http://muchs.cn/article12/pidodc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、全網(wǎng)營銷推廣品牌網(wǎng)站設(shè)計(jì)、電子商務(wù)、網(wǎng)頁設(shè)計(jì)公司網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管