成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

設(shè)計(jì)模式 單例模式

Sourcelink / 3442人閱讀

摘要:單例模式確保一個(gè)類只有一個(gè)實(shí)例,而且自動(dòng)實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。將構(gòu)造函數(shù)設(shè)置為私有的,防止外界出該類的實(shí)例,從而失去了單例的意義。這種實(shí)現(xiàn)的單例模式是最簡單的,同時(shí)多個(gè)線程操作該單例時(shí)也不會(huì)有問題。這就違反了單例模式。

單例模式

確保一個(gè)類只有一個(gè)實(shí)例,而且自動(dòng)實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。

實(shí)現(xiàn) 餓漢式

很簡單。

將構(gòu)造函數(shù)設(shè)置為私有的,防止外界new出該類的實(shí)例,從而失去了單例的意義。

設(shè)置類的私有靜態(tài)變量,同時(shí)新建單例對象。

添加共有靜態(tài)方法獲取該單例。

該種方法的缺點(diǎn)是在類加載時(shí)就進(jìn)行實(shí)例化,但是相較于其簡單易用來說,這點(diǎn)缺點(diǎn)個(gè)人認(rèn)為影響不大。

package com.mengyunzhi;

/**
 * @author zhangxishuo on 2018/6/18
 */
public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {
        return instance;
    }
}

這種實(shí)現(xiàn)的單例模式是最簡單的,同時(shí)多個(gè)線程操作該單例時(shí)也不會(huì)有問題。

package com.mengyunzhi;

public class Main {

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            Singleton singleton1 = Singleton.getInstance();
            System.out.println("Singleton1:" + singleton1);
        });
        Thread thread2 = new Thread(() -> {
            Singleton singleton2 = Singleton.getInstance();
            System.out.println("Singleton2:" + singleton2);
        });
        thread1.start();
        thread2.start();
    }
}

注:打印時(shí)調(diào)用toString方法,因?yàn)闆]有重寫toString,調(diào)用Object類中的toString,所以打印該對象的類名加哈希值。

我們看到控制臺中打印的兩個(gè)對象地址都是89ae60d,表示同一塊內(nèi)存,即表示多線程時(shí)該實(shí)現(xiàn)方法仍能實(shí)現(xiàn)單例。

線程競爭

我們調(diào)用的順序明明是thread1start,然后thread2start,但是為什么控制臺打印的順序卻是單例2和單例1呢?

這兩個(gè)線程會(huì)競爭處理器的資源,這里打印的順序是單例2、單例1,說明處理器處執(zhí)行線程時(shí),先執(zhí)行完thread2線程,后執(zhí)行完thread1線程。這兩個(gè)線程可能是同時(shí)執(zhí)行,也可能是來回切換執(zhí)行,這取決于處理器的核心與線程。

代碼講解

函數(shù)式接口

Thread類的構(gòu)造函數(shù)接收的是一個(gè)Runnable接口類型的參數(shù),所以之前創(chuàng)建線程的代碼長這樣。

Thread myThread = new Thread(new Runnable() {
    @Override
    public void run() {

    }
});

看下面的代碼,因?yàn)?b>Runnable接口只有一個(gè)抽象的run方法需要去實(shí)現(xiàn),所以就不需要去@Override聲明我要實(shí)現(xiàn)run方法,直接傳一個(gè)函數(shù)體不就可以嗎?這就是函數(shù)式接口。

package java.lang;

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

lamda表達(dá)式

相信很多人都聽說過lamda表達(dá)式,但是總是覺得這個(gè)很高大上,其實(shí)我們接觸過lamda表達(dá)式,只是沒有注意到。

self.init = function() {

};

JavaScript的世界里,我們可以將一個(gè)函數(shù)傳來傳去。

self.init = () => {

};

然后人們發(fā)現(xiàn),寫function太麻煩了,他們發(fā)明了箭頭函數(shù)。用這種寫法代替一個(gè)函數(shù)。

Java為什么不可以?

如果剛剛的代碼這么寫,那你應(yīng)該瞬間就明白了。

Runnable runnable = () -> {
    Singleton singleton1 = Singleton.getInstance();
    System.out.println("Singleton1:" + singleton1);
};
Thread thread1 = new Thread(runnable);
懶漢式

這是懶漢式的寫法,當(dāng)需要這個(gè)實(shí)例的時(shí)候,再去新建實(shí)例。

package com.mengyunzhi;

/**
 * @author zhangxishuo on 2018/6/18
 */
public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

但是這是這種寫法是線程不安全的,我們再運(yùn)行一下主函數(shù)中多個(gè)線程同時(shí)訪問單例的方法。

上次向晨澍請教:StringBuffer線程安全,StringBuilder線程不安全。既然有的類線程安全,有的類線程不安全?那為什么不都用線程安全的呢?

答案就是:為了實(shí)現(xiàn)線程安全,系統(tǒng)需要額外的開銷。所以有些不需要多線程的,使用線程不全的類,通常會(huì)提高速度。

假設(shè)我們的處理器支持多個(gè)線程并行處理,當(dāng)多個(gè)線程同時(shí)訪問時(shí),thread1獲取實(shí)例,然后判斷if (instance == null),創(chuàng)建實(shí)例;另一個(gè)線程同時(shí)執(zhí)行,instance依然是空,然后thread2調(diào)用getInstance時(shí)又創(chuàng)建了一個(gè)實(shí)例。這就違反了單例模式。

synchronized

解決該問題的方案就是用synchronized修飾該代碼塊。

音標(biāo):["s??kr?na?zd]

只允許一個(gè)線程訪問synchronized修飾的代碼塊,其他線程會(huì)被阻塞,等待該線程執(zhí)行完再執(zhí)行。

synchronized public static Singleton getInstance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
}

應(yīng)該是線程2先執(zhí)行完的,所以我們猜測就是:線程2競爭到處理器資源,然后去訪問getInstance()方法,因?yàn)楣P者屬于多核多線程處理器,支持線程并行執(zhí)行,當(dāng)線程2訪問getInstance()代碼塊時(shí),因?yàn)橛?b>synchronized修飾,所以線程1會(huì)被阻塞,等待線程2執(zhí)行完再才能訪問該代碼塊。

線程2執(zhí)行完創(chuàng)建實(shí)例,線程1可以訪問該代碼塊,發(fā)現(xiàn)instance不為空,直接返回。

使用場景

頻繁new然后銷毀的對象,降低了內(nèi)存開支。

當(dāng)一個(gè)對象的產(chǎn)生需要較多資源時(shí),如讀取配置,可以將其設(shè)置為單例,在應(yīng)用啟動(dòng)時(shí)產(chǎn)生一個(gè)單例對象常駐內(nèi)存。

單例是同一個(gè)對象,可以用該單例設(shè)置項(xiàng)目配置,用于幾個(gè)模塊之間共享。

擴(kuò)展:多線程學(xué)習(xí) 為什么要使用多線程?

摩爾定律

每18個(gè)月,芯片的性能將提高一倍。

單核心

十幾年前,那時(shí)還是單核的時(shí)代,各大廠商做出主頻越來越高的處理器。

但是主頻越高,意味著芯片中需要的晶體管越多,功耗越大,散熱越多,當(dāng)一定程度熱量就會(huì)燒壞芯片。

為什么CPU的頻率止步于4G?我們觸到頻率天花板了嗎?

2004年秋,IntelCEO公開對取消4GHz芯片的計(jì)劃道歉。

這是Intel酷睿i7 8700K的參數(shù),主頻僅有3.70GHz,十幾年過去了,我們依然停留在4GHz。

多核心

但是,為了滿足不斷增長的用戶需求,雖然無法提升單個(gè)核心的時(shí)鐘頻率,但是廠商利用多核心實(shí)現(xiàn)了芯片的性能提升。

這是Intel官網(wǎng)對i7 8700K的描述,6核心12線程。也就是說這個(gè)處理器有6個(gè)物理核心,因?yàn)槌€程技術(shù),可以模擬出12個(gè)邏輯核心,即可以同時(shí)處理12個(gè)線程任務(wù)。

超線程就是利用處理器剩余的資源模擬出一個(gè)新的核心,用于提高處理器的利用率。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/71245.html

相關(guān)文章

  • Android中的設(shè)計(jì)模式單例模式

    摘要:總結(jié)單例是運(yùn)用頻率很高的模式,因?yàn)榭蛻舳藳]有高并發(fā)的情況,選擇哪種方式并不會(huì)有太大的影響,出于效率考慮,推薦使用和靜態(tài)內(nèi)部類實(shí)現(xiàn)單例模式。 單例模式介紹 單例模式是應(yīng)用最廣的模式之一,也可能是很多人唯一會(huì)使用的設(shè)計(jì)模式。在應(yīng)用單例模式時(shí),單例對象的類必須保證只用一個(gè)實(shí)例存在。許多時(shí)候整個(gè)系統(tǒng)只需要一個(gè)全局對象,這樣有利于我么能協(xié)調(diào)整個(gè)系統(tǒng)整體的行為。 單例模式的使用場景 確保某個(gè)類有且...

    yzd 評論0 收藏0
  • JavaScript設(shè)計(jì)模式----單例模式

    摘要:不符合設(shè)計(jì)模式中的單一職責(zé)的概念。引入代理實(shí)現(xiàn)單例模式引入代理實(shí)現(xiàn)單例模式的特點(diǎn)我們負(fù)責(zé)管理單例的邏輯移到了代理類中。的單例模式對比在以上的代碼中實(shí)現(xiàn)的單例模式都混入了傳統(tǒng)面向?qū)ο笳Z言的特點(diǎn)。 聲明:這個(gè)系列為閱讀《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》 ----曾探@著一書的讀書筆記 1.單例模式的特點(diǎn)和定義 保證一個(gè)類僅有一個(gè)實(shí)例,并且提供一個(gè)訪問它的全局訪問點(diǎn)。 2.傳統(tǒng)面向?qū)?..

    selfimpr 評論0 收藏0
  • JavaScript設(shè)計(jì)模式-第一部分:單例模式、組合模式和外觀模式

    摘要:但是,這并不是采用單例的唯一原因。使用命名空間單例模式也被稱為模塊設(shè)計(jì)模式。函數(shù)內(nèi)部聲明了一些局部函數(shù)和或變量。緊隨函數(shù)聲明放置即可立即執(zhí)行外部函數(shù),并將所得的對象文字費(fèi)賠給變量。 JavaScript設(shè)計(jì)模式-第一部分:單例模式、組合模式和外觀模式 設(shè)計(jì)模式是一些可靠的編程方式,有助于保證代碼更加易于維護(hù)、擴(kuò)展及分離,所有設(shè)計(jì)模式在創(chuàng)建大型JavaScript應(yīng)用程序時(shí)均不可或缺 單...

    betacat 評論0 收藏0
  • Java設(shè)計(jì)模式-單例模式(Singleton Pattern)

    摘要:如果需要防范這種攻擊,請修改構(gòu)造函數(shù),使其在被要求創(chuàng)建第二個(gè)實(shí)例時(shí)拋出異常。單例模式與單一職責(zé)原則有沖突。源碼地址參考文獻(xiàn)設(shè)計(jì)模式之禪 定義 單例模式是一個(gè)比較簡單的模式,其定義如下: 保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。 或者 Ensure a class has only one instance, and provide a global point of ac...

    k00baa 評論0 收藏0
  • Java 設(shè)計(jì)模式單例模式

    摘要:在設(shè)計(jì)模式一書中,將單例模式稱作單件模式。通過關(guān)鍵字,來保證不會(huì)同時(shí)有兩個(gè)線程進(jìn)入該方法的實(shí)例對象改善多線程問題為了符合大多數(shù)程序,很明顯地,我們需要確保單例模式能在多線程的情況下正常工作。 在《Head First 設(shè)計(jì)模式》一書中,將單例模式稱作單件模式。這里為了適應(yīng)大環(huán)境,把它稱之為大家更熟悉的單例模式。 一、了解單例模式 1.1 什么是單例模式 單例模式確保一個(gè)類只有一個(gè)實(shí)例,...

    everfight 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<