亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

支持生產阻塞的Java線程池

2019-11-26 15:32:34
字體:
來源:轉載
供稿:網友

通常來說,生產任務的速度要大于消費的速度。一個細節問題是,隊列長度,以及如何匹配生產和消費的速度。

一個典型的生產者-消費者模型如下:

 

在并發環境下利用J.U.C提供的Queue實現可以很方便地保證生產和消費過程中的線程安全。這里需要注意的是,Queue必須設置初始容量,防止生產者生產過快導致隊列長度暴漲,最終觸發OutOfMemory。

對于一般的生產快于消費的情況。當隊列已滿時,我們并不希望有任何任務被忽略或得不到執行,此時生產者可以等待片刻再提交任務,更好的做法是,把生產者阻塞在提交任務的方法上,待隊列未滿時繼續提交任務,這樣就沒有浪費的空轉時間了。阻塞這一點也很容易,BlockingQueue就是為此打造的,ArrayBlockingQueue和LinkedBlockingQueue在構造時都可以提供容量做限制,其中LinkedBlockingQueue是在實際操作隊列時在每次拿到鎖以后判斷容量。

更進一步,當隊列為空時,消費者拿不到任務,可以等一會兒再拿,更好的做法是,用BlockingQueue的take方法,阻塞等待,當有任務時便可以立即獲得執行,建議調用take的帶超時參數的重載方法,超時后線程退出。這樣當生產者事實上已經停止生產時,不至于讓消費者無限等待。

于是一個高效的支持阻塞的生產消費模型就實現了。

等一下,既然J.U.C已經幫我們實現了線程池,為什么還要采用這一套東西?直接用ExecutorService不是更方便?

我們來看一下ThreadPoolExecutor的基本結構:

 

可以看到,在ThreadPoolExecutor中,BlockingQueue和Consumer部分已經幫我們實現好了,并且直接采用線程池的實現還有很多優勢,例如線程數的動態調整等。

但問題在于,即便你在構造ThreadPoolExecutor時手動指定了一個BlockingQueue作為隊列實現,事實上當隊列滿時,execute方法并不會阻塞,原因在于ThreadPoolExecutor調用的是BlockingQueue非阻塞的offer方法:

復制代碼 代碼如下:

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
        if (runState == RUNNING && workQueue.offer(command)) {
            if (runState != RUNNING || poolSize == 0)
                ensureQueuedTaskHandled(command);
        }
        else if (!addIfUnderMaximumPoolSize(command))
            reject(command); // is shutdown or saturated
    }
}

這時候就需要做一些事情來達成一個結果:當生產者提交任務,而隊列已滿時,能夠讓生產者阻塞住,等待任務被消費。

關鍵在于,在并發環境下,隊列滿不能由生產者去判斷,不能調用ThreadPoolExecutor.getQueue().size()來判斷隊列是否滿。

線程池的實現中,當隊列滿時會調用構造時傳入的RejectedExecutionHandler去拒絕任務的處理。默認的實現是AbortPolicy,直接拋出一個RejectedExecutionException。

幾種拒絕策略在這里就不贅述了,這里和我們的需求比較接近的是CallerRunsPolicy,這種策略會在隊列滿時,讓提交任務的線程去執行任務,相當于讓生產者臨時去干了消費者干的活兒,這樣生產者雖然沒有被阻塞,但提交任務也會被暫停。

復制代碼 代碼如下:

public static class CallerRunsPolicy implements RejectedExecutionHandler {
    /**
     * Creates a <tt>CallerRunsPolicy</tt>.
     */
    public CallerRunsPolicy() { }

    /**
     * Executes task r in the caller's thread, unless the executor
     * has been shut down, in which case the task is discarded.
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

但這種策略也有隱患,當生產者較少時,生產者消費任務的時間里,消費者可能已經把任務都消費完了,隊列處于空狀態,當生產者執行完任務后才能再繼續生產任務,這個過程中可能導致消費者線程的饑餓。

參考類似的思路,最簡單的做法,我們可以直接定義一個RejectedExecutionHandler,當隊列滿時改為調用BlockingQueue.put來實現生產者的阻塞:

復制代碼 代碼如下:

new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                if (!executor.isShutdown()) {
                        try {
                                executor.getQueue().put(r);
                        } catch (InterruptedException e) {
                                // should not be interrupted
                        }
                }
        }
};

這樣,我們就無需再關心Queue和Consumer的邏輯,只要把精力集中在生產者和消費者線程的實現邏輯上,只管往線程池提交任務就行了。

相比最初的設計,這種方式的代碼量能減少不少,而且能避免并發環境的很多問題。當然,你也可以采用另外的手段,例如在提交時采用信號量做入口限制等,但是如果僅僅是要讓生產者阻塞,那就顯得復雜了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩一区免费| 成人深夜直播免费观看| 久久精品视频导航| 综合激情国产一区| 亚洲视频在线免费观看| 亚洲精品国产电影| 亚洲色图av在线| 亚洲天堂精品在线| 欧美在线观看网站| 亚洲香蕉伊综合在人在线视看| 国产精品丝袜久久久久久不卡| 日韩久久免费电影| 国产精品久久久久久中文字| 欧美日韩中文在线观看| 久久精品99国产精品酒店日本| 国产精品一香蕉国产线看观看| 成人免费大片黄在线播放| 欧美亚洲视频在线看网址| 亚洲国产精品va在线观看黑人| 色视频www在线播放国产成人| 欧美激情一级二级| 日韩成人激情视频| 国产精品999999| 亚洲精品久久久一区二区三区| 日韩精品在线观| 国产不卡av在线| 国产精品无av码在线观看| 伊人久久五月天| 亚洲免费一在线| 亚洲第一中文字幕| 欧美日韩国产色| 精品国产福利在线| 亚洲午夜激情免费视频| 欧美日韩日本国产| 欧美日韩国产在线看| 日韩在线资源网| 久久久久久久久电影| 97精品国产97久久久久久免费| 亚洲精品久久久久久久久久久久| 亚洲国产精品女人久久久| 欧美日韩性生活视频| 国产精品久久久久久婷婷天堂| 日韩免费av片在线观看| 久久精品国产清自在天天线| 亚洲欧美日本精品| 亚洲一区第一页| 国产成人精品免费久久久久| 亚洲午夜av久久乱码| 国产精品久久婷婷六月丁香| 中文字幕在线看视频国产欧美| 亚洲激情中文字幕| 国产91ⅴ在线精品免费观看| 欧美性猛交xxxx久久久| 97国产一区二区精品久久呦| 国产精品久久久久久久久久| 亚洲一区二区三区在线视频| 中文字幕欧美日韩va免费视频| 国产精品日韩欧美| 中文字幕在线观看日韩| 成人精品aaaa网站| 亚洲欧美国内爽妇网| 91啪国产在线| 色噜噜亚洲精品中文字幕| 亚洲a级在线观看| 国内精品久久影院| 久久91亚洲人成电影网站| 神马国产精品影院av| 日韩在线中文字幕| 久久久久九九九九| 日韩av免费在线| 精品国产91乱高清在线观看| 91国产视频在线| 亚洲成人aaa| 亚洲国产免费av| 欧美日韩一区二区在线播放| 欧美高清激情视频| 国产精品一区二区久久精品| 米奇精品一区二区三区在线观看| 欧美国产亚洲视频| 国产91九色视频| 亚洲国产欧美精品| 欧美精品18videosex性欧美| 亚洲已满18点击进入在线看片| 国产精品揄拍一区二区| 欧美日韩激情视频| 日韩国产精品一区| 538国产精品一区二区免费视频| 亚洲欧美国产一区二区三区| 亚洲日本欧美日韩高观看| 日韩少妇与小伙激情| 秋霞成人午夜鲁丝一区二区三区| 日韩av黄色在线观看| 8x海外华人永久免费日韩内陆视频| 亚洲精品在线91| 91丨九色丨国产在线| 国产91ⅴ在线精品免费观看| 精品色蜜蜜精品视频在线观看| 国产精品av在线播放| 久久久久久久久中文字幕| 欧美老少配视频| 日韩中文字幕在线视频播放| 伊人久久精品视频| 两个人的视频www国产精品| 国产精品久久久久久久电影| 欧美—级高清免费播放| 亚洲成avwww人| 国产精品色婷婷视频| www.亚洲免费视频| 久久久成人精品视频| 亚洲精品小视频在线观看| 国产亚洲视频在线| 色老头一区二区三区在线观看| 亚洲精品999| 91亚洲精品在线观看| 日韩国产高清污视频在线观看| 欧美丝袜一区二区三区| 国产精品偷伦一区二区| 亚洲精品国产精品国产自| 午夜精品久久久久久久久久久久| 欧美日韩另类字幕中文| 国产精品日日摸夜夜添夜夜av| 亚洲黄色www| 一二美女精品欧洲| 欧美午夜精品久久久久久人妖| 久久久欧美一区二区| 激情久久av一区av二区av三区| 91精品国产综合久久男男| 在线观看欧美www| 国产精品高潮呻吟久久av无限| 国产精品pans私拍| 欧美性猛交xxxx久久久| 日韩视频永久免费观看| 狠狠色香婷婷久久亚洲精品| 欧美wwwxxxx| 国产精品久久久久久久久久久新郎| 欧美日韩精品在线观看| 亚洲**2019国产| 中文字幕日韩欧美在线| 久久天天躁夜夜躁狠狠躁2022| 91欧美激情另类亚洲| 亚洲精品不卡在线| 97av视频在线| 欧美激情网站在线观看| 欧美大尺度电影在线观看| 久久久av亚洲男天堂| 激情亚洲一区二区三区四区| 午夜精品福利在线观看| 国产精品影片在线观看| 成人免费视频网址| 亚洲精品视频免费在线观看| 国产精品爽爽爽| 欧美性猛交xxxx免费看久久久| 欧洲美女免费图片一区| 欧美怡春院一区二区三区| 亚洲级视频在线观看免费1级| 亚洲国内精品在线| 亚洲tv在线观看| 在线看国产精品| 日韩欧美成人网| 亚洲精品99久久久久| 91国产美女在线观看| 国产精品美女无圣光视频| 亚洲视频国产视频| 亚洲欧美国产高清va在线播|