亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

java多線程(6)線程池

RiverLi / 2978人閱讀

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

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

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

demo

先舉個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("耗時:"+(System.currentTimeMillis()-s1));
            System.out.println("AtomicLong="+al.get());

結果:

耗時: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("耗時:"+(System.currentTimeMillis()-s1));
                    System.out.println("AtomicLong="+al.get());
                    break;
                }
                Thread.sleep(1);
            }

結果:

耗時:2972
AtomicLong=20000

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

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

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

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

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

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

unit:keepAliveTime的單位。

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

threadFactory:生成新線程的工廠。

handler:當線程數(shù)超過workQueue的上限時,新線程會被拒絕,這個參數(shù)就是新線程被拒絕的方式。

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

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

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

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

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

Executors

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

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

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

把corePoolSize設為1,而workQueue大小設為無限大,因此永遠只有一個線程在執(zhí)行任務,新任務都在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所有新任務都會被立即執(zhí)行,corePoolSize 設置為0,maximumPoolSize設置為整數(shù)最大值,所有線程超過60秒未被使用,就會被銷毀。

workQueue

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

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

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

拒絕策略

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

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

1、AbortPolicy

直接拋出一個RejectedExecutionException,這也是JDK默認的拒絕策略

2、CallerRunsPolicy

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

3、DiscardOldestPolicy

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

4、DiscardPolicy

悄悄地拒絕任務

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

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/76376.html

相關文章

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

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

    AdolphLWQ 評論0 收藏0
  • 想進大廠?50個線程面試題,你會少?(一)

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

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

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

    wpw 評論0 收藏0
  • Java 并發(fā)方案全面學習總結

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

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

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

    dreamans 評論0 收藏0

發(fā)表評論

0條評論

RiverLi

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<