溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java線程池的原理和應用

發布時間:2020-06-24 09:16:48 來源:億速云 閱讀:182 作者:Leah 欄目:編程語言

這期內容當中小編將會給大家帶來有關java線程池的原理和應用,以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

線程池概述

1. 線程池就是一個管理線程的池子,可以降低創建和銷毀線程帶來的資源消耗

因為線程其實也是一個對象,創建一個對象,需要經過類加載過程,銷毀一個對象,需要走GC垃圾回收流程,都是需要資源開銷的。

2. 提高響應速度,任務到達了相對于從線程池取線程,自己創建線程肯定慢很多

3. 重復利用,線程用完了再放回池子,達到了重復利用的效果

線程池執行

打個比喻

核心線程比作公司正式員工

非核心線程比作外包員工

阻塞隊列比作需求池

提交任務比作提需求

java線程池的原理和應用

正式執行

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,
   BlockingQueue<Runnable> workQueue,
   ThreadFactory threadFactory,
   RejectedExecutionHandler handler)
corePoolSize     核心線程數
maximumPoolSize  線程池最大線程數
keepAliveTime    空閑線程存活時間
TimeUnit         線程空閑存活時間單位
workQueue        存放任務的阻塞隊列
threadFactory    線程工廠
handler          飽和策略

● 提交一個任務,線程池里存活的核心線程數小于線程數corePoolSize時,線程池會創建一個核心線程去處理提交的任務。

● 如果線程池核心線程數已滿,即線程數已經等于corePoolSize,一個新提交的任務,會被放進任務隊列workQueue排隊等待執行。

● 當線程池里面存活的線程數已經等于corePoolSize了,并且任務隊列workQueue也滿,判斷線程數是否達到maximumPoolSize,即最大線程數是否已滿,如果沒到達,創建一個非核心線程執行提交的任務。

● 如果當前的線程數達到了maximumPoolSize,還有新的任務過來的話,直接采用拒絕策略處理。

幾種飽和策略

AbortPolicy         拋出一個異常,默認的
DiscardPolicy       直接丟棄任務
DiscardOldestPolicy 丟棄隊列里最老的任務,將當前這個任務繼續提交給線程池
CallerRunsPolicy    交給線程池調用所在的線程進行處理

線程池異常處理

由于在線程池調用線程處理任務過程中出現的異??赡軙痪€程池捕獲,所以對于任務的執行可能是無感知的,因此我們需要考慮線程池異常情況。

方法一:

@Test
public void test1() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 5; i++) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("name: " + Thread.currentThread().getName());
                    Object a = null;
                    System.out.println(a.hashCode());
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        });
    }
}

方法二:

@Test
public void test2() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 20; i++) {
        Future<?> future = executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("name: " + Thread.currentThread().getName());
                Object a = null;
                System.out.println(a.hashCode());
            }
        });
        try {
            future.get();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

線程池的工作隊列

● ArrayBlockingQueue

● LinkedBlockingQueue

● SynchronousQueue

● DelayQueue

● PriorityBlockingQueue

==ArrayBlockingQueue==

● 初始化一定容量的數組

● 使用一個重入鎖,默認使用非公平鎖,入隊和出隊共用一個鎖,互斥

● 是有界設計,如果容量滿無法繼續添加元素直至有元素被移除

● 使用時開辟一段連續的內存,如果初始化容量過大容易造成資源浪費,過小易添加失敗

==LinkedBlockingQueue==

● 使用鏈表數據結構

● 非連續性內存空間

● 使用兩個重入鎖分別控制元素的入隊和出隊,用Condition進行線程間的喚醒和等待

● 有邊界的,在默認構造方法中容量是Integer.MAX_VALUE

==SynchronousQueue==

● 內部容量是0

● 每次刪除操作都要等待插入操作

● 每次插入操作都要等待刪除操作

● 一個元素,一旦有了插入線程和移除線程,那么很快由插入線程移交給移除線程,這個容器相當于通道,本身不存儲元素

● 在多任務隊列,是最快的處理任務方式。

==PriorityBlockingQueue==

● 無邊界設計,但容量實際是依靠系統資源影響

● 添加元素,如果超過1,則進入優先級排序

==DelayQueue==

● 無邊界設計

● 添加(put)不阻塞,移除阻塞

● 元素都有一個過期時間

● 取元素只有過期的才會被取出

常用的線程池

● newFixedThreadPool (固定數目線程的線程池)

● newCachedThreadPool (可緩存線程的線程池)

● newSingleThreadExecutor (單線程的線程池)

● newScheduledThreadPool (定時及周期執行的線程池)

==newFixedThreadPool==

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

特點

1. 核心線程數和最大線程數大小一樣

2. 沒有所謂的非空閑時間,即keepAliveTime為0

3. 阻塞隊列為無界隊列LinkedBlockingQueue

工作機制:

java線程池的原理和應用

● 提交任務

● 如果線程數少于核心線程,創建核心線程執行任務

● 如果線程數等于核心線程,把任務添加到LinkedBlockingQueue阻塞隊列

● 如果線程執行完任務,去阻塞隊列取任務,繼續執行。

==newCachedThreadPool==

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

線程池特點

● 核心線程數為0

● 最大線程數為Integer.MAX_VALUE

● 阻塞隊列是SynchronousQueue

● 非核心線程空閑存活時間為60秒

java線程池的原理和應用

工作機制:

● 提交任務

● 因為沒有核心線程,所以任務直接加到SynchronousQueue隊列。

● 判斷是否有空閑線程,如果有,就去取出任務執行。

● 如果沒有空閑線程,就新建一個線程執行。

● 執行完任務的線程,還可以存活60秒,如果在這期間,接到任務,可以繼續活下去;否則,被銷毀。

使用場景

用于并發執行大量短期的小任務。

使用SynchronousQueue作為工作隊列,工作隊列本身并不限制待執行的任務的數量。但此時需要限定線程池的最大大小為一個合理的有限值,而不是Integer.MAX_VALUE,否則可能導致線程池中的工作者線程的數量一直增加到系統資源所無法承受為止。

如果應用程序確實需要比較大的工作隊列容量,而又想避免無界工作隊列可能導致的問題,不妨考慮SynchronousQueue。SynchronousQueue實現上并不使用緩存空間

==newSingleThreadExecutor==

線程池特點

● 核心線程數為1

● 最大線程數也為1

● 阻塞隊列是LinkedBlockingQueue

● keepAliveTime為0

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

工作機制

java線程池的原理和應用

● 提交任務

● 線程池是否有一條線程在,如果沒有,新建線程執行任務

● 如果有,講任務加到阻塞隊列

● 當前的唯一線程,從隊列取任務,執行完一個,再繼續取,一個人(一條線程)夜以繼日地干活。

使用場景

適用于串行執行任務的場景,一個任務一個任務的執行

==newScheduledThreadPool==

線程池特點

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());
}

● 最大線程數為Integer.MAX_VALUE

● 阻塞隊列是DelayedWorkQueue

● keepAliveTime為0

● scheduleAtFixedRate() :按某種速率周期執行

● scheduleWithFixedDelay():在某個延遲后執行

工作機制

● 添加一個任務

● 線程池中的線程從 DelayQueue 中取任務

● 線程從 DelayQueue 中獲取 time 大于等于當前時間的task

● 執行完后修改這個 task 的 time 為下次被執行的時間

● 這個 task 放回DelayQueue隊列中

scheduleWithFixedDelay

● 無論任務執行時間長短,都是當第一個任務執行完成之后,延遲指定時間再開始執行第二個任務

scheduleAtFixedRate

● 在任務執行時間小于間隔時間的情況下,程序以起始時間為準則,每隔指定時間執行一次,不受任務執行時間影響

● 當執行任務時間大于間隔時間,此方法不會重新開啟一個新的任務進行執行,而是等待原有任務執行完成,馬上開啟下一個任務進行執行。此時,執行間隔時間已經被打亂

上述就是小編為大家分享的java線程池的原理和應用了,如果您也有類似的疑惑,不妨參照上述方法進行嘗試。如果想了解更多相關內容,請關注億速云行業資訊。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女