1. 程式人生 > 資訊 >公安部等三部門:平臺不得制定損害外賣騎手等勞動者安全健康的考核指標

公安部等三部門:平臺不得制定損害外賣騎手等勞動者安全健康的考核指標

(一)概述

1、沒有執行緒池的狀態:

當我們使用一條執行緒的時候,先將執行緒物件創建出來,啟動執行緒,在執行過程中,可能

能完成任務,也可能會在中途被任務內容中斷掉,任務還沒有完成。

即使是能夠正常完成,執行緒物件就結束了,就變成了垃圾物件,需要被垃圾回收器回收

如果在系統中,大量的任務都是小任務,任務消耗時間較短、執行緒物件的建立和消亡耗

費的時間比較多,結果:大部分的時間都浪費在了執行緒物件的建立和死亡上。

如果任務本身破壞力比較大,可能會把執行緒物件結束掉,就無法繼續完成任務。

2、有執行緒池的狀態

在沒有任務的時候,先把執行緒物件準備好,儲存到一個容器中,一旦有任務來的時候,

就不需要建立物件,而是直接將物件獲取出來執行任務

如果任務破壞力較小,任務可以直接完成,這個執行緒物件不會進入死亡狀態,而是被容

器回收,繼續活躍。

如果任務破壞力較大,任務會把執行緒搞死,執行緒池會繼續提供下一個執行緒,繼續完成這

個任務。

(二)使用

1、步驟:獲取執行緒池物件;建立任務類物件;將任務類物件提交到執行緒池中

2、獲取執行緒池物件:

工具類:Executors:生成執行緒池的工具類,根據需求生成指定大小的執行緒池

ExecutorService Executors.newSingleThreadPool():建立一個有單個執行緒的執行緒池

ExecutorService Executors.newFixedThreadPool(int nThreads):建立一個指定線

程數量的執行緒池

3、建立任務類物件:Runnable的實現類物件,用於定義任務內容

4、將任務類物件提交到執行緒池中ExecutorService:是一個介面,不需要手動建立這個介面的實現類物件,使用方法獲取

到的就是這個介面的實現類物件,一定可以呼叫這個介面中的方法

submit(Runnable r):可以將一個任務類物件,提交到執行緒池中,如果有空閒的執行緒,

就可以馬上執行這個任務,如果沒有空閒執行緒,那麼這個任務就需要等待。

shutDown():結束執行緒池,已經提交的全部保證完成,不準繼續提交了

shutDownNow():結束執行緒池,已經開始執行的,保證完成;但是還沒有執行的,已經提

交的,不給運行了,作為返回值範圍;對於沒有提交的,不準提交。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo15_UseThreadPool {

    public static void main(String[] args) {
        //執行緒池中執行緒的預設名稱:pool-1-thread-1

        /*
        * 當提交的任務數量多於池中執行緒數,則先給所有執行緒安排任務去執行,哪一個執行緒先執行完了自己的任務,就立馬執行排隊的任務
        *
        * */
        //1.獲取執行緒池:ThreadPoolExecutor
        ExecutorService es = Executors.newFixedThreadPool(2);

        //2.將任務提交到執行緒池
        //submit(Runnable task)
        Runnable task1 = new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("AAAAAAAAAAAAAAAAA" + Thread.currentThread().getName());

                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Runnable task2 = new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("@@@@@@@@@@@@@@@@@" + Thread.currentThread().getName());

                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Runnable task3 = new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("5555555555555555" + Thread.currentThread().getName());

                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        es.submit(task1);
        es.submit(task2);
        es.submit(task3);

        //關閉執行緒池,執行已經提交的任務和正在排隊的任務,不接受新任務
        es.shutdown();

        //關閉執行緒池,嘗試結束正在執行的任務,不執行正在排隊的任務,不接受新任務
        //es.shutdownNow();

    }
}

執行緒池原理

(一)執行緒池部分體系

1、Executor:介面,定義了一個接收 Runnable 物件的方法executor(Runnable

command)

2、ExecutorService:比 Executor 使用更廣泛的子介面

3、AbstractExecutorService:ExecutorService 抽象方法的實現類

4、ThreadPoolExecutor:執行緒池,可以通過呼叫 Executors 工具類的靜態工廠

方法來建立執行緒池並返回一個 ExecutorService 的實現類物件

(二)ThreadPoolExecutor類概述

1、Executors工具類,是建立執行緒池的工具類

2、ExecutorService介面,是工具類返回執行緒池物件所實現的介面

3、ThreadPoolExecutor是ExecutorService介面的實現類,就是返回的執行緒池對

象所屬類

4、ThreadPoolExecutor的構造方法:

ThreadPoolExecutor(intcorePoolSize, intmaximumPoolSize, longkeepAliveTime, TimeUnitunit, BlockingQueue<Runnable>workQueue, ThreadFactorythreadFactory, RejectedExecutionHandlerhandler)
用給定的初始引數建立新的 ThreadPoolExecutor

ThreadPoolExecutor(

int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

corePoolSize:

執行緒池的核心執行緒數。在建立了執行緒池後,預設情況下,

執行緒池中並沒有任何執行緒,當有任務來之後,就會建立一個執行緒去執行任務,

當執行緒池中的執行緒數目達到 corePoolSize 後,

就會把到多出的任務放到隊列當中

maximumPoolSize:

執行緒池允許建立的最大執行緒數。

如果佇列滿了,並且已建立的執行緒數小於最大執行緒數,

則執行緒池會再建立新的執行緒執行任務。

注意:如果使用了無界的任務佇列這個引數就沒什麼效果。

keepAliveTime:

執行緒活動保持時間。執行緒池的工作執行緒空閒後,保持存活的時間。

如果任務很多,並且每個任務執行的時間比較短,

可以調大這個時間,提高執行緒的利用率。

unit:

引數 keepAliveTime 的時間單位,在TimeUnit列舉類中,有 7 種取值。

可選的單位有天(DAYS),小時(HOURS),分鐘(MINUTES),

毫秒(MILLISECONDS),微秒(MICROSECONDS),納秒(NANOSECONDS)

用來指定keepAliveTime的單位,比如秒:TimeUnit.SECONDS

workQueue:

任務佇列。用於儲存等待執行的任務的阻塞佇列。

可以選擇有界佇列和無界佇列

threadFactory:

執行緒工廠,用來建立執行緒。主要是為了給執行緒起名字,

預設工廠的執行緒名字:pool‐1‐thread‐1

Executors工具類中的defaultThreadFactory()方法可以獲取到

用於建立新執行緒的預設執行緒工廠

handler:

拒絕策略,當執行緒池裡執行緒被耗盡,且佇列也滿了的時候會呼叫

(三)阻塞佇列和有界、無界佇列

1、阻塞佇列:是一個支援阻塞的插入和移除方法的佇列

(1)支援阻塞的插入方法:當佇列滿時,佇列會阻塞插入元素的執行緒,直

到佇列不滿

(2)支援阻塞的移除方法:當佇列為空時,獲取元素的執行緒會等待佇列變

為非空

2、有界佇列:具有固定大小的佇列,可以進隊的元素個數是有限的。

3、無界佇列:是沒有設定固定大小的佇列。這些佇列的特點是可以直接入列,

直到記憶體資源耗盡

4、相關型別即構造方法:

(1)ArrayBlockingQueue 基於陣列實現的有界阻塞佇列

(2)LinkedBlockingQueue 基於連結串列實現的佇列,可以設定為有界,不設

定則無界

(3)SynchronousQueue 無界無緩衝的佇列,內部容量為零,適用於元素數

量少的場景

(四)拒絕策略

1、ThreadPoolExecutor.AbortPolicy

(此項是預設策略)直接丟擲異常RejectedExecutionException

2、ThreadPoolExecutor.CallerRunsPolicy

該任務被執行緒池拒絕,由呼叫 execute方法的執行緒執行該任務

3、ThreadPoolExecutor.DiscardOldestPolicy

拋棄佇列最前面的任務,然後重新嘗試執行任務

4、ThreadPoolExecutor.DiscardPolicy

丟棄任務,也不會丟擲異常

(五)執行緒池執行流程

(六)有界佇列和無界佇列對執行緒池的影響

1、使用有界佇列:如果有新的任務需要執行,如果執行緒池時機執行緒數量小於核

心執行緒數corePoolSize,則優先建立執行緒。如果大於核心執行緒數corePoolSize,

則會將任務加入佇列。如果佇列已滿,則在匯流排程數量不大於最大執行緒數

maximumPoolSize的前提下,建立新的執行緒。如果執行緒數大於最大執行緒數

maximumPoolSize,則執行拒絕策略

2、使用無界佇列:除了系統資源耗盡,否則無界佇列不存在任務入隊失敗的情

況。當有任務到來,系統的執行緒數小於核心執行緒數corePoolSize時,新建執行緒執

行任務。如果後續仍然有新的任務加入,而沒有空閒的執行緒,則任務直接入隊等

待。如果任務處理慢,而任務新增快,則佇列會快速增長,直到系統資源耗盡。

(七)ThreadPoolExecutor原始碼分析