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

資訊專欄INFORMATION COLUMN

java多線程(6)線程池

RiverLi / 2897人閱讀

摘要:雖然使用很方便,但是建議大家使用已經(jīng)設(shè)定的幾種線程池?zé)o界線程池,可以進(jìn)行線程自動(dòng)回收固定大小線程池和單個(gè)后線程,它們滿足大部分的場(chǎng)景需求。固定大小線程池和有些類似,只不過從單線程變成可以指定線程數(shù)量,依舊為無限。

池的概念在java中也是常見,還有連接池、常量池等,池的作用也是類似的,對(duì)于對(duì)象、資源的重復(fù)利用,減小系統(tǒng)開銷,提升運(yùn)行效率。

線程池的主要功能:
1.減少創(chuàng)建和銷毀線程的次數(shù),提升運(yùn)行性能,尤其是在大量異步任務(wù)時(shí)
2.可以更合理地管理線程,如:線程的運(yùn)行數(shù)量,防止同一時(shí)間大量任務(wù)運(yùn)行,導(dǎo)致系統(tǒng)崩潰

demo

先舉個(gè)demo,看看使用線程池的區(qū)別,線程池:

AtomicLong al = new AtomicLong(0l);
            Long s1 = System.currentTimeMillis();
            ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 100000, 100, TimeUnit.SECONDS, new LinkedBlockingDeque(20000));
            for(int i=0;i<20000;i++){
                pool.execute(new Runnable() {
                    
                    @Override
                    public void run() {
                        try {
                            al.incrementAndGet();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            pool.shutdown();
            pool.awaitTermination(1, TimeUnit.HOURS);
            System.out.println("耗時(shí):"+(System.currentTimeMillis()-s1));
            System.out.println("AtomicLong="+al.get());

結(jié)果:

耗時(shí):224
AtomicLong=20000

非線程池:

AtomicLong al = new AtomicLong(0l);            
            Long s1 = System.currentTimeMillis();
            for(int i=0;i<20000;i++){
                Thread t = new Thread(new Runnable() {
                    
                    @Override
                    public void run() {
                        try {
                            al.incrementAndGet();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
                t.start();
            }
            while(true){
                if(al.get()==20000){
                    System.out.println("耗時(shí):"+(System.currentTimeMillis()-s1));
                    System.out.println("AtomicLong="+al.get());
                    break;
                }
                Thread.sleep(1);
            }

結(jié)果:

耗時(shí):2972
AtomicLong=20000

從耗時(shí)看2者相差了13倍,差距還是挺大的,可見有大量異步任務(wù)時(shí)使用線程池能夠提升性能。

線程池的主要參數(shù)
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {

線程池的主要參數(shù)有這6個(gè):

corePoolSize:核心池的大小,核心池的線程不會(huì)被回收,沒有任務(wù)就處于空閑狀態(tài)。

maximumPoolSize:線程池最大允許的線程數(shù),

keepAliveTime:當(dāng)線程數(shù)超過corePoolSize時(shí),但小于等于maximumPoolSize,會(huì)生成‘臨時(shí)’線程,‘臨時(shí)’線程執(zhí)行完任務(wù)不會(huì)馬上被回收,如果在keepAliveTime時(shí)間內(nèi),還沒有新任務(wù)的話,才會(huì)被回收。

unit:keepAliveTime的單位。

workQueue:當(dāng)前線程數(shù)超過corePoolSize大小時(shí),新任務(wù)會(huì)處在等待狀態(tài),存在workQueue中。

threadFactory:生成新線程的工廠。

handler:當(dāng)線程數(shù)超過workQueue的上限時(shí),新線程會(huì)被拒絕,這個(gè)參數(shù)就是新線程被拒絕的方式。

其中corePoolSize和maximumPoolSize相對(duì)難理解,再詳細(xì)說明:
1、池中線程數(shù)小于corePoolSize,新任務(wù)都不排隊(duì)而是直接添加新線程

2、池中線程數(shù)大于等于corePoolSize,workQueue未滿,首選將新任務(wù)加入workQueue而不是添加新線程

3、池中線程數(shù)大于等于corePoolSize,workQueue已滿,但是線程數(shù)小于maximumPoolSize,添加新的線程來處理被添加的任務(wù)

4、池中線程數(shù)大于大于corePoolSize,workQueue已滿,并且線程數(shù)大于等于maximumPoolSize,新任務(wù)被拒絕,使用handler處理被拒絕的任務(wù)

因此maximumPoolSize、corePoolSize不宜設(shè)置過大,否則會(huì)造成內(nèi)存、cpu過載的問題,workQueue而盡量可以大一些。

Executors

雖然ThreadPoolExecutor使用很方便,但是建議大家使用jdk已經(jīng)設(shè)定的幾種線程池:
Executors.newCachedThreadPool()(無界線程池,可以進(jìn)行線程自動(dòng)回收)、Executors.newFixedThreadPool(int)(固定大小線程池)和Executors.newSingleThreadExecutor()(單個(gè)后線程),它們滿足大部分的場(chǎng)景需求。

1.newSingleThreadExecutor 單線程線程池
看下它的實(shí)現(xiàn)方式:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
    }

把corePoolSize設(shè)為1,而workQueue大小設(shè)為無限大,因此永遠(yuǎn)只有一個(gè)線程在執(zhí)行任務(wù),新任務(wù)都在workQueue中等待。

2.newFixedThreadPool 固定大小線程池

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
    }

和newSingleThreadExecutor 有些類似,只不過從單線程變成可以指定線程數(shù)量,workQueue依舊為無限。
3.newCachedThreadPool

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
    }

newCachedThreadPool所有新任務(wù)都會(huì)被立即執(zhí)行,corePoolSize 設(shè)置為0,maximumPoolSize設(shè)置為整數(shù)最大值,所有線程超過60秒未被使用,就會(huì)被銷毀。

workQueue

當(dāng)前線程數(shù)超過corePoolSize大小時(shí),新任務(wù)會(huì)處在等待狀態(tài),存在workQueue中。workQueue的實(shí)現(xiàn)方式也就是任務(wù)的等待策略,分為3種:有限隊(duì)列、無限隊(duì)列、直接提交。

談?wù)勄?種,jdk使用了LinkedBlockingQueue而非ArrayBlockingQueue,有限隊(duì)列的優(yōu)勢(shì)在于對(duì)資源和效率更定制化的配置,但是對(duì)比無限隊(duì)列缺點(diǎn)也很明顯:

1).增加開發(fā)難度。需要考慮到corePoolSize ,maximumPoolSize,workQueue,3個(gè)參數(shù)大小,既要使任務(wù)高效地執(zhí)行,又要避免任務(wù)超量的問題,對(duì)于開發(fā)和測(cè)試的復(fù)雜度提高很多。
2).防止業(yè)務(wù)突刺。在互聯(lián)網(wǎng)應(yīng)用業(yè)務(wù)量暴增也是必須考慮的問題,在使用無限隊(duì)列時(shí),雖然執(zhí)行可能慢一點(diǎn),但是能保證執(zhí)行到。使用有限隊(duì)列,會(huì)出現(xiàn)任務(wù)拒絕的問題。
綜上考慮,更建議使用無限隊(duì)列,尤其是對(duì)于多線程不是很熟悉的朋友們。

拒絕策略

所謂拒絕策略之前也提到過了,任務(wù)太多,超過maximumPoolSize了怎么辦?當(dāng)然是接不下了,接不下那只有拒絕了。拒絕的時(shí)候可以指定拒絕策略,也就是一段處理程序。

決絕策略的父接口是RejectedExecutionHandler,JDK本身在ThreadPoolExecutor里給用戶提供了四種拒絕策略,看一下:

1、AbortPolicy

直接拋出一個(gè)RejectedExecutionException,這也是JDK默認(rèn)的拒絕策略

2、CallerRunsPolicy

嘗試直接運(yùn)行被拒絕的任務(wù),如果線程池已經(jīng)被關(guān)閉了,任務(wù)就被丟棄。

3、DiscardOldestPolicy

移除最晚的那個(gè)沒有被處理的任務(wù),然后執(zhí)行被拒絕的任務(wù)。同樣,如果線程池已經(jīng)被關(guān)閉了,任務(wù)就被丟棄了

4、DiscardPolicy

悄悄地拒絕任務(wù)

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

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

相關(guān)文章

  • 跟著阿里p7一起學(xué)java高并發(fā) - 第18天:玩轉(zhuǎn)java線程,這一篇就夠了

    摘要:高并發(fā)系列第篇文章。簡單的說,在使用了線程池之后,創(chuàng)建線程變成了從線程池中獲取一個(gè)空閑的線程,然后使用,關(guān)閉線程變成了將線程歸還到線程池。如果調(diào)用了線程池的方法,線程池會(huì)提前把核心線程都創(chuàng)造好,并啟動(dòng)線程池允許創(chuàng)建的最大線程數(shù)。 java高并發(fā)系列第18篇文章。 本文主要內(nèi)容 什么是線程池 線程池實(shí)現(xiàn)原理 線程池中常見的各種隊(duì)列 自定義線程創(chuàng)建的工廠 常見的飽和策略 自定義飽和策略 ...

    AdolphLWQ 評(píng)論0 收藏0
  • 想進(jìn)大廠?50個(gè)線程面試題,你會(huì)少?(一)

    摘要:下面是線程相關(guān)的熱門面試題,你可以用它來好好準(zhǔn)備面試。線程安全問題都是由全局變量及靜態(tài)變量引起的。持有自旋鎖的線程在之前應(yīng)該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網(wǎng)上流傳著,各種面試經(jīng)驗(yàn)及面試題,往往都是一大堆技術(shù)題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關(guān)線程的問題。Java語言一個(gè)重要的特點(diǎn)就是內(nèi)置了對(duì)并發(fā)的支持,讓Java大受企業(yè)和程序員...

    wow_worktile 評(píng)論0 收藏0
  • (十七)java線程之ThreadPoolExecutor

    摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言在之前的例子我們要?jiǎng)?chuàng)建多個(gè)線程處理一批任務(wù)的時(shí)候我是通過創(chuàng)建線程數(shù)組或者使用線程集合來管理的但是這樣做不太好因?yàn)檫@些線程沒有被重復(fù)利用所以這里要引入線程池今天我們就講線程 本人郵箱: 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kcogithub: https://github...

    wpw 評(píng)論0 收藏0
  • Java 并發(fā)方案全面學(xué)習(xí)總結(jié)

    摘要:進(jìn)程線程與協(xié)程它們都是并行機(jī)制的解決方案。選擇是任意性的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會(huì)補(bǔ)充一個(gè)新線程。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。 并發(fā)與并行的概念 并發(fā)(Concurrency): 問題域中的概念—— 程序需要被設(shè)計(jì)成能夠處理多個(gè)同時(shí)(或者幾乎同時(shí))發(fā)生的事件 并行(Parallel...

    mengera88 評(píng)論0 收藏0
  • JAVA 線程和并發(fā)基礎(chǔ)面試問答

    摘要:多線程和并發(fā)問題是技術(shù)面試中面試官比較喜歡問的問題之一。線程可以被稱為輕量級(jí)進(jìn)程。一個(gè)守護(hù)線程是在后臺(tái)執(zhí)行并且不會(huì)阻止終止的線程。其他的線程狀態(tài)還有,和。上下文切換是多任務(wù)操作系統(tǒng)和多線程環(huán)境的基本特征。 多線程和并發(fā)問題是 Java 技術(shù)面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應(yīng)該牢固的掌握J(rèn)ava多線程基礎(chǔ)知識(shí)來對(duì)應(yīng)日后碰到的問題。(...

    dreamans 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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