国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

線程池是如何執(zhí)行的?任務(wù)太多會怎么?

這篇具有很好參考價值的文章主要介紹了線程池是如何執(zhí)行的?任務(wù)太多會怎么?。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Java 面試不可能不問線程池,無論是大廠還是小廠。這不,前幾天面試阿里時也被問到了這個問題,雖不難,但這里也系統(tǒng)復盤一下。

要搞懂線程池的執(zhí)行流程,最好的方式是去看它的源碼,它的源碼如下:

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    // 當前工作的線程數(shù)小于核心線程數(shù)
    if (workerCountOf(c) < corePoolSize) {
        // 創(chuàng)建新的線程執(zhí)行此任務(wù)
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // 檢查線程池是否處于運行狀態(tài),如果是則把任務(wù)添加到隊列
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 再次檢線程池是否處于運行狀態(tài),防止在第一次校驗通過后線程池關(guān)閉
        // 如果是非運行狀態(tài),則將剛加入隊列的任務(wù)移除
        if (! isRunning(recheck) && remove(command))
            reject(command);
        // 如果線程池的線程數(shù)為 0 時(當 corePoolSize 設(shè)置為 0 時會發(fā)生)
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false); // 新建線程執(zhí)行任務(wù)
    }
    // 核心線程都在忙且隊列都已爆滿,嘗試新啟動一個線程執(zhí)行失敗
    else if (!addWorker(command, false)) 
        // 執(zhí)行拒絕策略
        reject(command);
}

從上述源碼我們可以看出,當任務(wù)來了之后,線程池的執(zhí)行流程是:先判斷當前線程數(shù)是否大于核心線程數(shù)?如果結(jié)果為 false,則新建線程并執(zhí)行任務(wù);如果結(jié)果為 true,則判斷任務(wù)隊列是否已滿?如果結(jié)果為 false,則把任務(wù)添加到任務(wù)隊列中等待線程執(zhí)行,否則則判斷當前線程數(shù)量是否超過最大線程數(shù)?如果結(jié)果為 false,則新建線程執(zhí)行此任務(wù),否則將執(zhí)行線程池的拒絕策略,如下圖所示:
image.png

線程池拒絕策略

當任務(wù)過多且線程池的任務(wù)隊列已滿時,此時就會執(zhí)行線程池的拒絕策略,線程池的拒絕策略默認有以下 4 種:

  1. AbortPolicy:中止策略,線程池會拋出異常并中止執(zhí)行此任務(wù);
  2. CallerRunsPolicy:把任務(wù)交給添加此任務(wù)的(main)線程來執(zhí)行;
  3. DiscardPolicy:忽略此任務(wù),忽略最新的一個任務(wù);
  4. DiscardOldestPolicy:忽略最早的任務(wù),最先加入隊列的任務(wù)。

默認的拒絕策略為 AbortPolicy 中止策略。

DiscardPolicy拒絕策略

接下來我們以 DiscardPolicy 忽略此任務(wù),忽略最新的一個任務(wù)為例,演示一下拒絕策略的具體使用,實現(xiàn)代碼如下:

public static void main(String[] args) {
    // 任務(wù)的具體方法
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("當前任務(wù)被執(zhí)行,執(zhí)行時間:" + new Date() +
                               " 執(zhí)行線程:" + Thread.currentThread().getName());
            try {
                // 等待 1s
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    // 創(chuàng)建線程,線程的任務(wù)隊列的長度為 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,
                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new ThreadPoolExecutor.DiscardPolicy());
    // 添加并執(zhí)行 4 個任務(wù)
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    // 線程池執(zhí)行完任務(wù),關(guān)閉線程池
    threadPool.shutdown();
}

以上程序的執(zhí)行結(jié)果如下:
image.png
從上述執(zhí)行結(jié)果可以看出,給線程池添加了 4 個任務(wù),而線程池只執(zhí)行了 2 個任務(wù)就結(jié)束了,其他兩個任務(wù)執(zhí)行了拒絕策略 DiscardPolicy 被忽略了,這就是拒絕策略的作用。

AbortPolicy拒絕策略

為了和 DiscardPolicy 拒絕策略對比,我們來演示一下 JDK 默認的拒絕策略 AbortPolicy 中止策略,線程池會拋出異常并中止執(zhí)行此任務(wù),示例代碼如下:

public static void main(String[] args) {
    // 任務(wù)的具體方法
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("當前任務(wù)被執(zhí)行,執(zhí)行時間:" + new Date() +
                               " 執(zhí)行線程:" + Thread.currentThread().getName());
            try {
                // 等待 1s
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    // 創(chuàng)建線程,線程的任務(wù)隊列的長度為 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,
                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new ThreadPoolExecutor.AbortPolicy()); // 顯式指定拒絕策略,也可以忽略此設(shè)置,它為默認拒絕策略
    // 添加并執(zhí)行 4 個任務(wù)
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    // 線程池執(zhí)行完任務(wù),關(guān)閉線程池
    threadPool.shutdown();
}

以上程序的執(zhí)行結(jié)果如下:
image.png
從結(jié)果可以看出,給線程池添加了 4 個任務(wù),線程池正常執(zhí)行了 2 個任務(wù),其他兩個任務(wù)執(zhí)行了中止策略,并拋出了拒絕執(zhí)行的異常 RejectedExecutionException。

自定義拒絕策略

當然除了 JDK 提供的四種拒絕策略之外,我們還可以實現(xiàn)通過 new RejectedExecutionHandler,并重寫 rejectedExecution 方法來實現(xiàn)自定義拒絕策略,實現(xiàn)代碼如下:

public static void main(String[] args) {
    // 任務(wù)的具體方法
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("當前任務(wù)被執(zhí)行,執(zhí)行時間:" + new Date() +
                               " 執(zhí)行線程:" + Thread.currentThread().getName());
            try {
                // 等待 1s
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    // 創(chuàng)建線程,線程的任務(wù)隊列的長度為 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,
                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new RejectedExecutionHandler() {
                                                               @Override
                                                               public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                                                                   // 執(zhí)行自定義拒絕策略的相關(guān)操作
                                                                   System.out.println("我是自定義拒絕策略~");
                                                               }
                                                           });
    // 添加并執(zhí)行 4 個任務(wù)
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
}

以上程序的執(zhí)行結(jié)果如下:
image.png

小結(jié)

線程池的執(zhí)行流程有 3 個重要的判斷點(判斷順序依次往后):判斷當前線程數(shù)和核心線程數(shù)、判斷當前任務(wù)隊列是否已滿、判斷當前線程數(shù)是否已達到最大線程數(shù)。如果經(jīng)過以上 3 個判斷,得到的結(jié)果都會 true,則會執(zhí)行線程池的拒絕策略。JDK 提供了 4 種拒絕策略,我們還可以通過 new RejectedExecutionHandler 并重寫 rejectedExecution 方法來實現(xiàn)自定義拒絕策略。

本文已收錄至《Java面試突擊》,專注 Java 面試 100 年,查看更多:www.javacn.site文章來源地址http://www.zghlxwxcb.cn/news/detail-462939.html

到了這里,關(guān)于線程池是如何執(zhí)行的?任務(wù)太多會怎么?的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • for循環(huán)內(nèi)線程池并發(fā)執(zhí)行任務(wù),等到子線程全部處理完任務(wù),主線程在執(zhí)行java的實現(xiàn)方式

    for循環(huán)內(nèi)線程池并發(fā)執(zhí)行任務(wù),等到子線程全部處理完任務(wù),主線程在執(zhí)行 方式一 使用 CountDownLatch 在 Java 中,您可以使用 CountDownLatch 來實現(xiàn)主線程等待子線程執(zhí)行完成的功能。CountDownLatch 是一個同步工具類,它允許一個或多個線程等待其他線程完成操作后再繼續(xù)執(zhí)行。 具

    2024年02月11日
    瀏覽(22)
  • 使用多線程執(zhí)行任務(wù),并獲取返回結(jié)果,附異步實現(xiàn)

    使用多線程執(zhí)行任務(wù),并獲取返回結(jié)果,附異步實現(xiàn)

    這里創(chuàng)建了一個包含三個線程的固定線程池 線程池的介紹 根據(jù)主機情況實現(xiàn)自定義線程池: 也可以通過繼承 ThreadPoolExecutor 類來實現(xiàn)一個自定義線程池工具類。ThreadPoolExecutor 是 Java 標準庫中提供的一個線程池實現(xiàn),通過繼承它,我們可以實現(xiàn)自定義的線程池。 下面是一個繼

    2024年02月16日
    瀏覽(15)
  • SpringBoot數(shù)據(jù)源——為什么平時默認線程池是Hikari

    本文主要對DataSourceAutoConfiguration類進行講解,然后對這個類的注解做一個解釋,所以直接打開這個類,開始看…… ps:我用的版本是2.3.0.RELEASE 目錄 DataSourceAutoConfiguration類注解 @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @ConditionalOnMis

    2024年02月06日
    瀏覽(57)
  • 【Android】使用 `reactor.core.scheduler.Schedulers` 提供的線程池讓開發(fā)者更加靈活地執(zhí)行任務(wù)

    在 Android 開發(fā)中,使用 reactor.core.scheduler.Schedulers 提供的線程池可以讓開發(fā)者更加靈活地執(zhí)行任務(wù),并且可以根據(jù)具體情況選擇最合適的線程。 下面列舉幾種常用的線程池和其適用場景: Schedulers.single() :該調(diào)度器會使用單個線程來執(zhí)行任務(wù),適用于需要按照先后順序依次執(zhí)

    2024年02月09日
    瀏覽(15)
  • 并發(fā)編程5:如何執(zhí)行任務(wù)?

    目錄 1、線程中執(zhí)行任務(wù)的方式 2、Executor 框架 2.1 - 線程的執(zhí)行策略 2.2 - 線程池 2.3 - Executor 的生命周期 2.4 - 延任務(wù)與周期任務(wù) 3、找出可利用的并行性-代碼示例 3.1 - 單線程的 I/O 操作 3.2 - 攜帶任務(wù)結(jié)果的 Callable 與 Future(重要) 3.3 - 使用 Future 實現(xiàn)頁面渲染器 3.5 - Completio

    2024年02月11日
    瀏覽(15)
  • 如何查看Crontab任務(wù)是否執(zhí)行

    編寫了一條crontab如下: 可以通過以下兩種方式查看是否任務(wù)已經(jīng)執(zhí)行。 1、通過/var/log/cron文件查看。 可以看到最后一行,已經(jīng)執(zhí)行。 2、通過/var/spool/cron/root的郵件通知進行查看。 可以看到郵件通知(Cron Daemon)已經(jīng)執(zhí)行了。 參考文檔: 1、 https://blog.csdn.net/liaoyanyunde/article/det

    2024年02月01日
    瀏覽(29)
  • js中如何順序執(zhí)行異步任務(wù)

    在js中,任務(wù)可分為兩種,同步任務(wù)和異步任務(wù)。 (1) 同步任務(wù) 又叫 非耗時任務(wù) ,指的是在主線程排隊執(zhí)行的那些任務(wù) 只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù) (2) 異步任務(wù) 又叫 耗時任務(wù) ,異步任務(wù)由JavaScript委托給宿主環(huán)境進行執(zhí)行 當異步任務(wù)執(zhí)行完成后,會通知

    2024年02月09日
    瀏覽(24)
  • xxljob后臺集群部署如何避免重復執(zhí)行任務(wù)

    xxljob后臺集群部署如何避免重復執(zhí)行任務(wù)

    工作中有一場景,后臺部署2個節(jié)點,同時注冊到執(zhí)行器內(nèi),如何避免任務(wù)重復執(zhí)行呢? 其實xxl-job本身已經(jīng)考慮到這一點,我們只需要在創(chuàng)建任務(wù)的時候這樣做就可以了: 路由策略:選擇 一致性HASH 阻塞處理策略:選擇 丟棄后續(xù)調(diào)度 引自:xxl-job官網(wǎng)

    2024年02月13日
    瀏覽(33)
  • 如何讓Task在非線程池線程中執(zhí)行?

    如何讓Task在非線程池線程中執(zhí)行?

    Task承載的操作需要被調(diào)度才能被執(zhí)行,由于.NET默認采用基于線程池的調(diào)度器,所以Task默認在線程池線程中執(zhí)行。但是有的操作并不適合使用線程池,比如我們在一個ASP.NET Core應(yīng)用中承載了一些需要長時間執(zhí)行的后臺操作,由于線程池被用來處理HTTP請求,如果這些后臺操作也

    2024年02月06日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包