最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程常見案例分析線程池與單例模式及阻塞隊(duì)列

 更新時(shí)間:2022年05月13日 10:45:40   作者:Pretend..  
這篇文章主要介紹了多線程的常見案例,線程池(重點(diǎn))、單例模式、阻塞隊(duì)列,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下

一、單例模式

設(shè)計(jì)模式:軟件設(shè)計(jì)模式

是一套被反復(fù)使用、多數(shù)人知曉、經(jīng)過分類編目、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性、程序的重用性。

單例模式:是設(shè)計(jì)模式的一種。保證某個(gè)類在程序中只存在唯一一份實(shí)例,不會(huì)創(chuàng)建出多個(gè)實(shí)例。單例模式的具體實(shí)現(xiàn)分為“懶漢”和“餓漢”兩種。

構(gòu)造方法必須是私有的,保證該類不能在類外被隨便創(chuàng)建。

1、餓漢模式

類加載的同時(shí),創(chuàng)建實(shí)例。(缺點(diǎn)是無論是否使用都會(huì)創(chuàng)建對象,比較占空間)

//類加載的時(shí)候創(chuàng)建對象,確保只能有一個(gè)實(shí)例對象
class Singleton {
    private static Singleton instance = new Singleton();
    //私有的構(gòu)造方法
    private Singleton() {}
    //只能通過getInstance()方法獲取到同一個(gè)實(shí)例對象
    public static Singleton getInstance() {
        return instance;
    }
}

2、懶漢模式(單線程)

類加載的時(shí)候不創(chuàng)建實(shí)例,第一次使用的時(shí)候才創(chuàng)建實(shí)例。

(缺點(diǎn):線程不安全,如果存在多個(gè)線程并發(fā)并行執(zhí)行,可能創(chuàng)建多個(gè)實(shí)例,所以只適用于單線程)

class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        //第一次使用時(shí),創(chuàng)建實(shí)例
        if (instance == null) {
            instance = new Singleton();
        }
        //后面使用時(shí),直接返回第一次創(chuàng)建的實(shí)例
        return instance;
    }
}

3、懶漢模式(多線程)

上面的懶漢模式存在線程安全問題,如果多個(gè)線程同時(shí)調(diào)用getInstance()方法,可能創(chuàng)建多個(gè)實(shí)例。所以在多線程時(shí),我們需要使用synchronized改善線程安全問題。

class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    //加鎖保證不會(huì)有多個(gè)線程同時(shí)訪問改代碼塊
    public synchronized static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

對于以上代碼,雖然保證了線程安全,但是對于懶漢模式,只有在第一次調(diào)用時(shí)才會(huì)創(chuàng)建實(shí)例,大多數(shù)境況下只進(jìn)行讀操作,如果對代碼塊整體加鎖,程序執(zhí)行的效率會(huì)大大降低。我們可以對上面的程序進(jìn)一步優(yōu)化,對于讀操作,我們使用volatile修飾變量;只給寫操作的代碼塊加上鎖即可。

【單例模式懶漢模式多線程的進(jìn)一步優(yōu)化】雙重if判定

class Singleton {
    //使用volatile修飾變量
    private static volatile Singleton instance = null;
    private Singleton() {};
    public static Singleton getInstance() {
        if (instance == null) {
            //只給寫操作的相關(guān)代碼加鎖
            synchronized (Singleton.class) {
                //需要雙重if判斷,防止在多線程中加鎖前instance發(fā)生變化
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

寫操作加鎖,保證線程安全;

如果已經(jīng)實(shí)例化,進(jìn)行讀操作,保證多個(gè)線程并發(fā)并行執(zhí)行,保證效率。

二、阻塞隊(duì)列

阻塞隊(duì)列是什么?

阻塞隊(duì)列是一種特殊的隊(duì)列。也遵守“先進(jìn)先出”的原則。

阻塞隊(duì)列是一種線程安全的數(shù)據(jù)結(jié)構(gòu):

  • 當(dāng)隊(duì)列滿的時(shí)候,繼續(xù)入隊(duì)隊(duì)列就會(huì)阻塞,知道有其他線程從隊(duì)列中取走元素;
  • 當(dāng)隊(duì)列空的時(shí)候,繼續(xù)出隊(duì)也會(huì)阻塞,直到其他線程往隊(duì)列中插入元素。

阻塞隊(duì)列的一個(gè)經(jīng)典應(yīng)用場景就是“生產(chǎn)者消費(fèi)者模型”。

標(biāo)準(zhǔn)庫中的阻塞隊(duì)列:

  • BlockingQueue是一個(gè)接口,真是實(shí)現(xiàn)的是類是:LinkedBlockingQueue。
  • put方法用于阻塞式的入隊(duì)列,take用于阻塞式的出隊(duì)列。
  • BlockingQueue也有offer、poll、peek方法,但是不具有阻塞特性。

阻塞隊(duì)列的實(shí)現(xiàn)

  • 通過循環(huán)隊(duì)列實(shí)現(xiàn);
  • 使用synchronized進(jìn)行加鎖控制
  • put插入元素,如果隊(duì)列滿了,就進(jìn)行wait(要在循環(huán)中進(jìn)行wait,多線程情況下可能喚醒多個(gè)線程,所以喚醒后隊(duì)列可能還是滿的)
  • take取出元素,如果隊(duì)列為空,就wait(循環(huán)中wait)
public class BlockingQueue{
    //使用循環(huán)數(shù)組來實(shí)現(xiàn)阻塞隊(duì)列
    private int[] array;
    //隊(duì)列中已經(jīng)存放元素的個(gè)數(shù)
    private int size;
    //放入元素的下標(biāo)
    private int putIndex;
    //取元素的下標(biāo)
    private int takeIndex;
    //在構(gòu)造方法中指定隊(duì)列的大小
    public BlockingQueue(int capacity){
        array=new int[capacity];
    }
    /*放元素:需要保證線程安全,如果隊(duì)列滿了,線程進(jìn)入等待*/
    public synchronized void put(int m) throws InterruptedException {
        //隊(duì)列滿,線程等待
        if(size==array.length){
            //需要注意的是,進(jìn)行等待的是當(dāng)顯得實(shí)例對象,不是類對象
            this.wait();
        }
        //放元素,同時(shí)更新下標(biāo)
        array[putIndex]=m;
        putIndex=(putIndex+1)%array.length;
        size++;
        //通知等待的線程
        notifyAll();
    }
    /*取元素:保證線程安全。如果隊(duì)列為空,線程等待*/
    public synchronized int take() throws InterruptedException {
        //隊(duì)列為空,線程等待
        if(size==0){
            this.wait();
        }
        //取元素,同時(shí)更新下標(biāo)
        int ret=array[takeIndex];
        takeIndex=(takeIndex+1)%array.length;
        size--;
        //通知等待的線程
        notifyAll();
        return ret;
    }
}

生產(chǎn)者消費(fèi)者模型

生產(chǎn)者消費(fèi)者模型就是通過一個(gè)容器來解決生產(chǎn)者和消費(fèi)者之間的強(qiáng)耦合問題。

生產(chǎn)者和消費(fèi)者之間不直接通信,而通過阻塞隊(duì)列來實(shí)現(xiàn)通訊,所以生產(chǎn)者生產(chǎn)完數(shù)據(jù)不需要等待消費(fèi)者來處理,直接扔給阻塞隊(duì)列。消費(fèi)者也不需要去找生產(chǎn)者,而是直接從阻塞隊(duì)列中取。

  • 阻塞隊(duì)列相當(dāng)于一個(gè)緩沖區(qū),平衡了消費(fèi)者和生產(chǎn)者的處理能力;
  • 阻塞隊(duì)列也能使生產(chǎn)者和消費(fèi)者之間“解耦”。

耦合和解耦:

  • 耦合指的是兩個(gè)類之間聯(lián)系的緊密程度。強(qiáng)耦合(表示類之間存在著直接的關(guān)系)。弱耦合(在兩個(gè)類的中間加入一層,將原來的之間關(guān)系變成間接關(guān)系,使得兩個(gè)類對中間層是強(qiáng)耦合,兩個(gè)類之間變成了弱耦合。
  • 解耦:降低耦合度,也就是將強(qiáng)耦合變成弱耦合的過程。

三、線程池

池:字符串常量池(類似緩存)、數(shù)據(jù)庫連接池等

線程池:初始化的時(shí)候就創(chuàng)建一定數(shù)量的線程【不同的從線程池的阻塞隊(duì)列中取任務(wù)(消費(fèi)者)】【在其他線程中提交任務(wù)到線程池(生產(chǎn)者)】

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

線程的創(chuàng)建和銷毀都有一定的代價(jià),使用線程池就可以重復(fù)使用線程來執(zhí)行多組任務(wù)。(如果線程不再使用,并不是真正的將線程釋放,而是放到一個(gè)“池子”中,下次如果需要用到線程直接從池子中取,不必通過系統(tǒng)來創(chuàng)建)

1、創(chuàng)建線程池的的方法

(1)ThreadPoolExecutor

提供了更多的可選參數(shù),可以進(jìn)一步細(xì)化線程池行為的設(shè)定。

以第三個(gè)構(gòu)造方法為例:

  1. corePoolSize:表示核心線程的數(shù)量
  2. maximumPoolSize:最大線程數(shù)(核心線程+臨時(shí)線程)
  3. keepAliveTime:允許臨時(shí)線程空閑的時(shí)間(如果超過該時(shí)間臨時(shí)線程還是沒有任務(wù)執(zhí)行,就被銷毀)
  4. unit: keepaliveTime的時(shí)間單位
  5. workQueue:傳遞任務(wù)的阻塞隊(duì)列
  6. threadFactory:規(guī)定創(chuàng)建線程的標(biāo)準(zhǔn)
  7. RejectedExecutionHandler:拒絕策略,如果阻塞隊(duì)列已滿,再傳進(jìn)來任務(wù)該怎么辦

【1】AbortPolicy():超過負(fù)荷,直接拋出異常(默認(rèn)的拒絕策略,使用其他不帶拒絕策略的構(gòu)造方法時(shí)的默認(rèn)參數(shù))

【2】CallerRunsPolicy():調(diào)用者負(fù)責(zé)處理

【3】DiscardOldestPolicy():丟棄隊(duì)列中最老的任務(wù)

【4】DiscardPolicy():丟棄新來的任務(wù)

創(chuàng)建線程池如下:

        //使用ThreadPoolExecutor創(chuàng)建線程池
        ThreadPoolExecutor threadPool1=new ThreadPoolExecutor(
                5,
                10,
                3,
                //自由線程無任務(wù)時(shí)最大存活時(shí)間單位:分
                TimeUnit.MINUTES,
                //一般不使用無邊界的阻塞隊(duì)列,內(nèi)存有限
                new ArrayBlockingQueue<>(100),
                //規(guī)定創(chuàng)建線程的標(biāo)準(zhǔn)
                Executors.defaultThreadFactory(),
                //拒絕策略:一般最多使用CallerRunsPolicy(),或自己實(shí)現(xiàn)
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

(2)Executors(快捷創(chuàng)建線程池的API)

Executors創(chuàng)建線程的幾種方式:

  • newFixedThreadPool:創(chuàng)建固定線程數(shù)的線程池(沒有臨時(shí)線程)
  • newCachedThreadPool:創(chuàng)建線程數(shù)目動(dòng)態(tài)增長的線程池(緩存的線程池,沒有核心線程,全是臨時(shí)線程)
  • newSingleThreadExecutor:創(chuàng)建只包含單個(gè)線程的線程池
  • newScheduledThreadPool:設(shè)定延遲時(shí)間后執(zhí)行任務(wù),或者定期執(zhí)行命令(計(jì)劃線程池)

創(chuàng)建線程池如下:

        //Executors的四種創(chuàng)建線程的方法
        //沒有臨時(shí)線程的線程池
        ExecutorService threadPool2= Executors.newFixedThreadPool(10);
        //線程數(shù)目動(dòng)態(tài)增長的線程池
        ExecutorService threadPool3=Executors.newCachedThreadPool();
        //創(chuàng)建單個(gè)線程的線程池
        ExecutorService threadPool4=Executors.newSingleThreadExecutor();
        //計(jì)劃線程池
        ExecutorService threadPool5=Executors.newScheduledThreadPool(7);

2、線程池的工作流程

線程池工作流程

使用線程池:

創(chuàng)建線程池

提交任務(wù):

【1】submit(Runnable task)

【2】execute(Runnable task)

到此這篇關(guān)于Java多線程常見案例分析線程池與單例模式及阻塞隊(duì)列的文章就介紹到這了,更多相關(guān)Java線程池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java程序生成Access文件代碼實(shí)例

    Java程序生成Access文件代碼實(shí)例

    這篇文章主要介紹了Java程序生成Access文件代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • springboot+mybatis-plus實(shí)現(xiàn)自動(dòng)建表的示例

    springboot+mybatis-plus實(shí)現(xiàn)自動(dòng)建表的示例

    本文主要介紹了springboot+mybatis-plus實(shí)現(xiàn)自動(dòng)建表的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • 教你如何在 javadoc 輸出<> 符號(hào)

    教你如何在 javadoc 輸出<> 符號(hào)

    在 javadoc 輸出 <> 兩個(gè)符號(hào),直接使用會(huì)提示錯(cuò)誤,今天通過本文教大家如何在 javadoc 輸出<> 符號(hào),需要的朋友可以參考下
    2023-05-05
  • 在Java中如何決定使用 HashMap 還是 TreeMap

    在Java中如何決定使用 HashMap 還是 TreeMap

    這篇文章主要介紹了在Java中如何決定使用 HashMap 還是 TreeMap,很多朋友對這樣的問題很迷茫,下面小編給大家?guī)硪黄恼聨椭蠹伊私?,需要的朋友可以參考?/div> 2019-10-10
  • SpringBoot利用AOP實(shí)現(xiàn)一個(gè)日志管理詳解

    SpringBoot利用AOP實(shí)現(xiàn)一個(gè)日志管理詳解

    目前有這么個(gè)問題,有兩個(gè)系統(tǒng)CSP和OMS,這倆系統(tǒng)共用的是同一套日志操作:Log;目前想?yún)^(qū)分下這倆系統(tǒng)的日志操作,那沒辦法了,只能重寫一份Log的日志操作。本文就將利用AOP實(shí)現(xiàn)一個(gè)日志管理,需要的可以參考一下
    2022-09-09
  • springboot2.0?@Slf4j?log?彩色日志配置輸出到文件

    springboot2.0?@Slf4j?log?彩色日志配置輸出到文件

    這篇文章主要介紹了springboot2.0 @Slf4j log日志配置輸出到文件(彩色日志),解決方式是使用了springboot原生自帶的一個(gè)log框架,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • Spring中配置Transaction與不配置的區(qū)別及說明

    Spring中配置Transaction與不配置的區(qū)別及說明

    這篇文章主要介紹了Spring中配置Transaction與不配置的區(qū)別及說明,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 實(shí)現(xiàn)Java線程的取值并返回的方法

    實(shí)現(xiàn)Java線程的取值并返回的方法

    在本篇文章中我們給大家分享了關(guān)于Java線程的取值并返回的實(shí)現(xiàn)方法,對此有需要的朋友們可以跟著學(xué)習(xí)參考下。
    2018-10-10
  • Java?JDK的多版本共存實(shí)現(xiàn)方法

    Java?JDK的多版本共存實(shí)現(xiàn)方法

    有時(shí)候系統(tǒng)中需要多個(gè)jdk版本共存,我們在做特定的操作時(shí)需要特定的版本,這篇文章主要給大家介紹了關(guān)于Java?JDK的多版本共存實(shí)現(xiàn)?的相關(guān)資料,需要的朋友可以參考下
    2023-09-09
  • Java多線程+鎖機(jī)制實(shí)現(xiàn)簡單模擬搶票的項(xiàng)目實(shí)踐

    Java多線程+鎖機(jī)制實(shí)現(xiàn)簡單模擬搶票的項(xiàng)目實(shí)踐

    鎖是一種同步機(jī)制,用于控制對共享資源的訪問,在線程獲取到鎖對象后,可以執(zhí)行搶票操作,本文主要介紹了Java多線程+鎖機(jī)制實(shí)現(xiàn)簡單模擬搶票的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02

最新評論

甘德县| 东兰县| 曲阳县| 长沙县| 大余县| 昂仁县| 宜阳县| 晋中市| 郸城县| 留坝县| 安阳市| 贡嘎县| 股票| 祁连县| 泗水县| 沙湾县| 石城县| 许昌县| 新龙县| 昌宁县| 普格县| 拉萨市| 东乌珠穆沁旗| 库尔勒市| 惠来县| 武冈市| 十堰市| 惠安县| 洪泽县| 黎城县| 牙克石市| 嘉定区| 乌鲁木齐县| 柳江县| 望奎县| 南皮县| 江孜县| 太湖县| 铜川市| 宣城市| 乌鲁木齐市|