欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 實(shí)例解析單例模式

 更新時(shí)間:2021年11月01日 09:03:45   作者:FranzLiszt1847  
單例模式(Singleton Pattern)是 Java 中最簡單的設(shè)計(jì)模式之一。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式,這種模式涉及到一個(gè)單一的類,該類負(fù)責(zé)創(chuàng)建自己的對(duì)象,同時(shí)確保只有單個(gè)對(duì)象被創(chuàng)建

單例模式的介紹

單例對(duì)象(Singleton)是一種常用的設(shè)計(jì)模式。在實(shí)際使用中,單例對(duì)象能保證在一個(gè)JVM中,該對(duì)象只存在一個(gè)實(shí)例存在。

優(yōu)點(diǎn)

1、減少系統(tǒng)開銷,提高系統(tǒng)性能
2、省去了new操作符,降低了系統(tǒng)內(nèi)存的使用頻率,減輕GC壓力
3、避免對(duì)共享資源的多重占用

缺點(diǎn)

1、不適應(yīng)用多變的對(duì)象
2、擴(kuò)展困難
3、單例類的職責(zé)過重,在一定程度上違背了“單一職責(zé)原則”。

Synchronized

Synchronized示例

介紹單例模式前,我們現(xiàn)介紹一下Synchronized
示例如下:
建立一個(gè)內(nèi)部類,并開啟子線程,如果實(shí)例該類,則自動(dòng)執(zhí)行test1()方法

 class SynchronizedTest implements Runnable {
    private int count;

    public SynchronizedTest() {
        count = 0;
    }

    @Override
    public void run() {
        test1();
    }

    private void test1() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + count++);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

構(gòu)造一個(gè)SynchronizedTest 對(duì)象,傳入兩個(gè)線程對(duì)象

 SynchronizedTest test = new SynchronizedTest();
        Thread thread1 = new Thread(test,"test1");
        Thread thread2 = new Thread(test,"test2");
        thread1.start();
        thread2.start();

由結(jié)果可知,當(dāng)一個(gè)對(duì)象持有該代碼塊時(shí),另一個(gè)線程訪問不到被鎖住的代碼塊,只要當(dāng)前一線程執(zhí)行完成,另一線程才能執(zhí)行。

test1:0
test1:1
test1:2
test1:3
test1:4
test2:5
test2:6
test2:7
test2:8
test2:9

Synchronized與非Synchronized

建立一個(gè)內(nèi)部類

 class SynchronizedTest implements Runnable {
    private int count;

    public SynchronizedTest() {
        count = 0;
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("S")) {
            test1();
        } else {
            test2();
        }
    }

    public void test1() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void test2() {
        for (int i = 0; i < 5; i++) {
            try {
                System.out.println(Thread.currentThread().getName() + ":" + count);
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 }
SynchronizedTest test = new SynchronizedTest();
        Thread thread1 = new Thread(test,"S");
        Thread thread2 = new Thread(test,"N");
        thread1.start();
        thread2.start();

由結(jié)果可知,一個(gè)線程訪問Synchronized修飾的代碼塊,另一個(gè)線程訪問非Synchronized代碼塊不受阻塞

S:0
N:1
N:2
S:1
N:2
S:2
S:3
N:4
S:4
N:5

Singleton

第一個(gè)示例

此示例實(shí)現(xiàn)了單例,但是如果放在多線程當(dāng)中,將會(huì)漏洞百出
我們接著看下一個(gè)改良示例

public class Singleton {
/* 持有私有靜態(tài)實(shí)例,防止被引用,此處賦值為null,目的是實(shí)現(xiàn)延遲加載 */
private static Singleton instance = null;
    /* 私有構(gòu)造方法,防止被實(shí)例化 */
    private Singleton() {
    }
    /* 靜態(tài)工程方法,創(chuàng)建實(shí)例 */
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

第二個(gè)示例

根據(jù)第一個(gè)示例,我們進(jìn)行改良,加上Synchronized。
但是每次調(diào)用getInstance()方法時(shí),都會(huì)對(duì)對(duì)象上鎖,為了減少系統(tǒng)開銷,我們一般在第一次創(chuàng)建對(duì)象的時(shí)候加鎖,后面就不需要了
我們接著看下一個(gè)改良示例

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

第三個(gè)示例

我們對(duì)上一個(gè)示例進(jìn)行改良,只有在instance == null的時(shí)候,也就是第一次創(chuàng)建對(duì)象的時(shí)候,執(zhí)行加鎖的區(qū)域。此種寫法解決了上一個(gè)示例遺留的問題,但是在Java指令中創(chuàng)建對(duì)象和賦值操作是分開進(jìn)行的,也就是說instance = new Singleton();語句是分兩步執(zhí)行的。但是JVM并不保證這兩個(gè)操作的先后順序,也就是說有可能JVM會(huì)為新的Singleton實(shí)例分配空間,然后直接賦值給instance成員,然后再去初始化這個(gè)Singleton實(shí)例。

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

第四個(gè)示例

此代碼初看已經(jīng)沒有問題,如果在構(gòu)造方法中出現(xiàn)異常,那么實(shí)例將得不到創(chuàng)建

public class Singleton {
/* 私有構(gòu)造方法,防止被實(shí)例化 */
private Singleton() {
}
/* 此處使用一個(gè)內(nèi)部類來維護(hù)單例 */
private static class SingletonFactory {
private static Singleton instance = new Singleton();
  }
/* 獲取實(shí)例 */
public static Singleton getInstance() {
return SingletonFactory.instance;
  }
}

第五個(gè)示例

   private static Singleton instance = null;
   private Singleton(){

    }
    public static Singleton getInstance(){
        if (instance == null){
            sync();
        }
        return instance;
    }
   private static synchronized void sync(){
        if (instance == null){
           instance = new Singleton();
            System.out.println("success");
       }
    }

到此這篇關(guān)于Java 實(shí)例解析單例模式的文章就介紹到這了,更多相關(guān)Java 單例模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)二分法查找出數(shù)組重復(fù)數(shù)字

    java實(shí)現(xiàn)二分法查找出數(shù)組重復(fù)數(shù)字

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)二分法查找出數(shù)組重復(fù)數(shù)字,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Spring多定時(shí)任務(wù)@Scheduled執(zhí)行阻塞問題解決

    Spring多定時(shí)任務(wù)@Scheduled執(zhí)行阻塞問題解決

    這篇文章主要介紹了Spring多定時(shí)任務(wù)@Scheduled執(zhí)行阻塞問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 如何查找YUM安裝的JAVA_HOME環(huán)境變量詳解

    如何查找YUM安裝的JAVA_HOME環(huán)境變量詳解

    這篇文章主要給大家介紹了關(guān)于如何查找YUM安裝的JAVA_HOME環(huán)境變量的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • 從入門到精通:Java List遍歷修改的完全指南

    從入門到精通:Java List遍歷修改的完全指南

    在Java中,我們經(jīng)常需要遍歷List集合并對(duì)其中的元素進(jìn)行修改,這可以通過使用迭代器或for循環(huán)來實(shí)現(xiàn),需要的朋友可以參考下
    2023-10-10
  • POI通過模板導(dǎo)出EXCEL文件的實(shí)例

    POI通過模板導(dǎo)出EXCEL文件的實(shí)例

    下面小編就為大家?guī)硪黄狿OI通過模板導(dǎo)出EXCEL文件的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • 詳解java 三種調(diào)用機(jī)制(同步、回調(diào)、異步)

    詳解java 三種調(diào)用機(jī)制(同步、回調(diào)、異步)

    這篇文章主要介紹了java 三種調(diào)用機(jī)制(同步、回調(diào)、異步),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Spring boot 集成 Druid 數(shù)據(jù)源過程詳解

    Spring boot 集成 Druid 數(shù)據(jù)源過程詳解

    這篇文章主要介紹了Spring boot 集成 Druid 數(shù)據(jù)源過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Java?split方法使用超詳細(xì)講解

    Java?split方法使用超詳細(xì)講解

    這篇文章主要給大家介紹了關(guān)于Java?split方法使用的相關(guān)資料,Java中的我們可以利用split把字符串按照指定的分割符進(jìn)行分割,然后返回字符串?dāng)?shù)組,需要的朋友可以參考下
    2023-10-10
  • maven之packaging標(biāo)簽的使用

    maven之packaging標(biāo)簽的使用

    這篇文章主要介紹了maven之packaging標(biāo)簽的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Spring Boot+Shiro實(shí)現(xiàn)一個(gè)Http請(qǐng)求的Basic認(rèn)證

    Spring Boot+Shiro實(shí)現(xiàn)一個(gè)Http請(qǐng)求的Basic認(rèn)證

    本文向向大家仔細(xì)的介紹了如何使用Shiro實(shí)現(xiàn)一個(gè)Http請(qǐng)求的Basic認(rèn)證,有此需求的朋友可以參考下本文
    2021-06-06

最新評(píng)論