工做三年,小胖不知道線程池的拒絕策略?真的菜!

01線程池的拒絕策略

由於線程池是在提交任務時根據狀況執行拒絕策略的,而提交任務涉及兩個方法: execute 和 sumbit。在說拒絕策略以前,先談談這兩方法的區別。前端

1.1何時執行拒絕策略?

先看看 submit 的源碼:能夠看到它最終仍是調用 execute 方法。與 execute 的區別就是:能夠接收線程池執行的返回值,而 execute () 不能接收返回值java

public Future < ? > submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture < Void > ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}

再看 execute 源碼,註釋寫得很清楚了,簡單說下,分爲三步:面試

  • 當工做線程小於核心線程時,直接提交執行就完事了。
  • 線程池處於運行狀態,提交任務到隊列。再次檢查狀態,若非運行狀態,則移除任務並執行拒絕策略;不然,建立線程執行任務。
  • 線程池處於非運行狀態或者啓動線程執行失敗,則執行拒絕策略。
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    // 當前工做的線程數小於核心線程數
    if (workerCountOf(c) < corePoolSize) {
        // 建立新的線程執行此任務
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // 檢查線程池是否處於運行狀態,若是是則把任務添加到隊列
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 再次檢查線程池是否處於運行狀態,防止在第一次校驗經過後線程池關閉
        // 若是是非運行狀態,則將剛加入隊列的任務移除,並執行拒絕策略
        if (!isRunning(recheck) && remove(command))
            reject(command);
        // 若是線程池的線程數爲 0 時(當 corePoolSize 設置爲 0 時會發生)
        // 新建線程執行任務
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    // 核心線程都在忙且隊列都已爆滿,嘗試新啓動一個線程執行失敗
    } else if (!addWorker(command, false))
        // 執行拒絕策略
        reject(command);
}

02 Java 提供的拒絕策略

Java 給咱們提供了拒絕策略,建立線程池時就能夠指定拒絕策略,好比:算法

newThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue < > (),
    new ThreadPoolExecutor.AbortPolicy());

固然,你也能夠本身實現~數據庫

上面瞭解了拒絕策略的執行時機,再來看看 Java 給咱們提供的拒絕策略。分爲四種,關係以下:編程

拒絕策略.png

逐個聊聊它們的特色:設計模式

  • AbortPolicy:線程池默認的拒絕策略(不值當就是它),拒絕任務時,直接拋出一個類型爲 RejectedExecutionException 的運行時異常。你能夠捕獲逐個異常並根據本身的業務進行處理。
  • DiscardPolicy:這種很是粗暴,拒絕任務時不通知你。至關於,這個任務提沒有提交成功,你是不知道的,很是不友好。
  • DiscardOldestPolicy:看名字就知道跟第二種差很少,同樣不通知。區別在於:它拋棄的任務一般是隊列的頭結點,也就是存活時間最長的任務。
  • CallerRunsPolicy:這種最友好。線程池沒能力執行任務,就把這個任務交於提交任務的線程執行,也就是誰提交誰執行(並不必定是主線程提交任務)。這樣作有兩點好處:一是新提交任務不被丟棄,不會形成數據丟失;二是由於誰提交誰執行,當任務執行耗時比較長,它也就不會去提交任務,減緩任務提交的速度,線程池中的線程能夠趁機執行掉一部分任務,至關於給線程提供一個緩衝期。

總結

本文從源碼分析了拒絕策略的執行時機並詳細介紹了 Java 提供的四種拒絕策略,相信你們看完會有所收穫。選用哪一種線程池是根據你本身的業務而定的,實踐出真知。微信

小福利

若是看到這裏,喜歡這篇文章的話,請幫點個好看。微信搜索一個優秀的廢人,關注後回覆電子書送你 1000+ 本編程電子書 ,不僅 Java 哦,詳情看下圖。回覆 1024送你一套完整的某課網 java 就業班視頻教程。數據結構

資源

C語言

C++

Java

Git

Python

GO

Linux

經典必讀

面試相關

前端

人工智能

設計模式

數據庫

數據結構與算法

計算機基礎

一個優秀的廢人

相關文章
相關標籤/搜索