成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

java的線程池原理是什么

這篇文章將為大家詳細講解有關java的線程池原理是什么,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

成都創(chuàng)新互聯(lián)始終堅持【策劃先行,效果至上】的經營理念,通過多達十載累計超上千家客戶的網(wǎng)站建設總結了一套系統(tǒng)有效的推廣解決方案,現(xiàn)已廣泛運用于各行各業(yè)的客戶,其中包括:三輪攪拌車等企業(yè),備受客戶贊美。

    在之前已經使用過線程池了。在使用中,基本上就是初始化好線程池的實例之后,把任務丟進去,等待調度執(zhí)行就可以了。使用起來非常簡單方便。

new Thread弊端

  • 每次new Thread新建對象,性能差

  • 線程缺乏統(tǒng)一管理,可能無限制的新建線程,相互競爭,有可能占用過多系統(tǒng)資源導致死機或者OOM

  • 缺少更多功能,如更多執(zhí)行、定期執(zhí)行、線程中斷

線程池的好處

  • 重用存在的線程,減少對象創(chuàng)建、消亡的開銷,性能好

  • 可以有效控制最大并發(fā)線程數(shù),提高系統(tǒng)資源利用率,同時可以避免過多資源競爭,避免阻塞

  • 提供定時執(zhí)行、定期執(zhí)行、單線程、并發(fā)數(shù)控制等高級功能

ThreadPoolExecutor

參數(shù):

  • corePoolSize:核心線程數(shù)量。建議和cpu的核心數(shù)差不多,當有任務提交,檢測當前線程池內的線程數(shù)小于corePoolSize的話,新建線程執(zhí)行任務,而不會開始復用,會新建,直到達到corePoolSize。線程池內的線程數(shù)大于等于corePoolSize時,將任務放入workQueue等待。

  • maximumPoolSize:允許線程池內最大線程數(shù)。當隊列滿了之后,如果線程池內的線程數(shù)小于maximumPoolSize則新建線程,如果大于等于執(zhí)行拒絕策略。
    如果maximumPoolSize是30,corePoolSize是10,當隊列滿了后只能再開20個線程。

  • workQueue:阻塞隊列,存儲等待執(zhí)行的任務,很重要,會對線程池運行過程產生重大影響

  • keepAliveTime:線程沒有任務執(zhí)行時最多保持多久時間終止。線程池維護線程所允許的空閑時間。當線程池中的線程數(shù)量大于CorePoolSize時,如果這是沒有新的任務提交,線程會等待,直到時間超過keepAliveTime才銷毀。

  • unit:keepAliveTime的時間單位

  • threadFactory:線程工廠,用來創(chuàng)建線程,會有一個默認的工廠來創(chuàng)建線程。使用默認的工廠創(chuàng)建線程時,線程擁有相同的優(yōu)先級,并且是非守護的線程,同時也設置了線程的名稱。

  • rejectHandle:當拒絕處理任務時的策略。如果workQueue阻塞隊列滿了,并且沒有空閑的線程時,這時還繼續(xù)提交任務,我們就需要一種策略來處理這個任務。線程池總共提供了四種策略:

    1. 直接拋出異常,默認策略

    2.  用調用者所在的線程執(zhí)行任務

    3. 丟棄隊列中最靠前的任務,并執(zhí)行當前任務

    4. 直接丟棄這個任務

    如果運行的線程數(shù)小于CorePoolSize時,直接創(chuàng)建新線程創(chuàng)建任務,即使線程池中的其他線程是空閑的。

    如果線程池中的線程數(shù)量大于等于CorePoolSize且小于maximumPoolSize時,則只有當wokQueue滿時才創(chuàng)建新的線程去處理任務。

    如果我們設置CorePoolSize與maximumPoolSize相等,那么創(chuàng)建的線程池大小是固定的,這時如果有新任務提交且workQueue還沒滿,就把請求放入workQueue中,等待空閑線程從workQueue中取任務進行處理。

    如果運行的線程數(shù)量大于maximumPoolSize時,這時如果workQueue滿,那么會通過一個拒絕策略參數(shù)來指定策略處理任務。

    如果我們想降低系統(tǒng)資源的消耗,包括CPU的使用率、操作系統(tǒng)資源的消耗,可以設置一個較大的workQueue容量和較小的CorePoolSize容量,這樣會降低線程處理的吞吐量。如果我們提交的任務經常發(fā)生阻塞,我們可以設置maximumPoolSize來設置線程池容量。如果我們隊列容量較小,通常需要把maximumPoolSize設置大一些,這樣CPU使用率會高一些。但是如果線程池容量設置過大,在提交人物數(shù)量過多的情況下,并發(fā)量會增加,那么線程間資源調度就是一個需要考慮的問題,反而會降低處理的吞吐量。

線程池狀態(tài)

java的線程池原理是什么

當我們初始化一個線程池之后,通常有上面幾種狀態(tài)。

running:可以接受新提交的任務,也能處理阻塞隊列中的任務。

shutdown:關閉狀態(tài),當一個線程池實例處于shutdown狀態(tài)時,不能再接收新提交的任務,但卻可以繼續(xù)處理阻塞隊列中已經保存的任務。

stop:也不能接收新的任務,也不處理隊列中的任務。會中斷正在處理的線程任務。

tidying:所有任務都已經終止了,沒有活動中的線程。當線程池進行該狀態(tài)時候,會執(zhí)行鉤子方法terminated() 。

ThreadPoolExecutor中的方法

  1. execute():提交任務,交給線程池執(zhí)行

  2. submit():提交任務,能夠返回執(zhí)行結果 相當于execute+Future

  3. shutdown():關閉線程池,等待任務都執(zhí)行完

  4. shutdownNow():關閉線程池,不等待任務執(zhí)行完

  5. getTaskCount():線程池已執(zhí)行和未執(zhí)行的任務總數(shù)

  6. getCompletedTaskCount():已完成的任務數(shù)量

  7. getPoolSize():線程池當前的線程數(shù)量

  8. getActiveCount():當前線程池中正在執(zhí)行任務的線程數(shù)量

java的線程池原理是什么

Executors框架接口

  • Executors.newCachedThreadPool:創(chuàng)建一個可緩存的線程池,如果線程池的長度超過了線程的需要,可以靈活回收空閑線程,如果沒有回收的,可以新建線程

  • Executors.newFixedThreadPool:創(chuàng)建一個定長的線程池,可以控制線程的最大并發(fā)數(shù),超出的線程會在隊列中等待

  • Executors.newScheduledThreadPool:也是創(chuàng)建一個定長的線程池。支持定時以及周期性的任務執(zhí)行。

  • Executors.newSingleThreadExecutor:創(chuàng)建一個單線程的線程池,會用唯一的工作線程來執(zhí)行任務。保證所有任務按照指定順序去執(zhí)行(先入先出等)。

 Executors.newCachedThreadPool示例代碼:

@Slf4j
public class ThreadPoolExample1 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i< 10; i++){
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("task:{}", index);
                }
            });
        }
        //一定要關閉線程池,否則程序不結束
        executorService.shutdown();
    }
}

Executors.newSingleThreadExecutor示例代碼:

@Slf4j
public class ThreadPoolExample3 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i< 10; i++){
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("task:{}", index);
                }
            });
        }
        //一定要關閉線程池,否則程序不結束
        executorService.shutdown();
    }
}

輸出結果:

17:08:16.870 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:0
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:1
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:2
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:3
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:4
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:5
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:6
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:7
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:8
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:9

相當于單線程按順序執(zhí)行。  

Executors.newScheduledThreadPool代碼示例:

@Slf4j
public class ThreadPoolExample4 {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                log.warn("schedule run");
            }
        },1, 3, TimeUnit.SECONDS);
        //這里不需要關閉線程池
        //scheduledExecutorService.shutdown();
    }
}

上面目的是:延遲1秒后,每個三秒執(zhí)行一次任務,由于這個任務時不定的執(zhí)行,因此這里不應該關閉線程池。如果需要關閉線程池的話,可以設置一個觸發(fā)條件來關閉。類似于Timer類:

@Slf4j
public class ThreadPoolExample4 {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.warn("timer run");
            }
        }, new Date(), 5*1000);
    }
}

線程池合理配置

  • CPU密集型任務,就需要盡量壓榨CPU,參考值可以設置為NCPU+1

  • 如果是IO密集型任務,參考值可以設置為2*NCPU

    我們只用線程池主要是為了重用存在的線程,減少對象創(chuàng)建消亡,能有效控制最大線程并發(fā)數(shù),可以避免過多的資源競爭和阻塞,也可以定時執(zhí)行單線程與控制線程的執(zhí)行性能比較好。 這不代表線程池應該隨時隨地用,一定要根據(jù)自己的實際場景來分析使用參數(shù)配置

關于java的線程池原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

名稱欄目:java的線程池原理是什么
路徑分享:http://jinyejixie.com/article34/iisdse.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設計公司、網(wǎng)站策劃、用戶體驗、App設計、微信公眾號、全網(wǎng)營銷推廣

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

外貿網(wǎng)站制作
微山县| 麦盖提县| 洞头县| 巴中市| 浦县| 响水县| 日照市| 安化县| 灌阳县| 宁陵县| 溧水县| 沽源县| 滦南县| 龙胜| 唐河县| 句容市| 泾川县| 临颍县| 达拉特旗| 黄浦区| 板桥市| 洪洞县| 梓潼县| 湾仔区| 当涂县| 河源市| 桐梓县| 定结县| 宁陕县| 新宾| 麦盖提县| 金溪县| 平江县| 许昌县| 阳谷县| 乐陵市| 东乌珠穆沁旗| 宜兰市| 蓬安县| 腾冲县| 玉山县|