JDK執行緒池簡介與使用
阿新 • • 發佈:2019-09-29
一、執行緒池簡介
- 為了避免系統頻繁的建立和銷燬執行緒,我們可以將建立的執行緒進行復用。資料庫中的資料庫連線池也是此意。Java中的執行緒池是運用場景最多的併發框架,幾乎所有需要非同步或併發執行任務的程式都可以使用執行緒池。在開發過程中,合理地使用執行緒池能夠帶來以下好處:
- 第一:降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。
- 第二:提高響應速度。當任務到達時,任務可以不需要等到執行緒建立就能立即執行。
- 第三:提高執行緒的可管理性。執行緒是稀缺資源,如果無限制地建立,不僅會消耗系統資源,還會降低系統的穩定性,使用執行緒池可以進行統一分配、調優和監控。但是,要做到合理利用執行緒池,必須對其實現原理了如指掌。
- 線上程池中總有那麼幾個活躍的執行緒,也有一定的最大值限制,一個業務使用完執行緒之後,不是立即銷燬而是將其放入到執行緒池中,從而實現執行緒的複用。簡而言之:建立執行緒變成了從執行緒池獲取空閒的執行緒,關閉執行緒變成了向池子中歸還執行緒。
二、JDK對執行緒池的支援
- 為了更好的控制多執行緒,JDK提供了一套執行緒框架Executor,幫助開發人員有效的進行執行緒控制。他們都在java.util.concurrent包中,時JDK併發包的核心。其中一個比較重要的類:Executors,扮演者執行緒工廠的角色,我們通過Executors可以建立特定功能的執行緒池。 Executors建立執行緒池的方法:
- newFixedThreadPool()方法,該方法返回一個固定數量的執行緒池,該方法的執行緒數始終不變,當有一個任務提交時,若執行緒池中空閒,則立即執行,若沒有,則會被暫緩在一個任務佇列中等待有空閒的執行緒去執行。
- newSingleThreadExecutor()方法,建立一個執行緒的執行緒池,若空閒則執行,若沒有空閒則暫緩在任務佇列中。
- newCachedThreadPool()方法,返回一個可根據實際情況調整執行緒個數的執行緒池,不限制最大執行緒數量,若用空閒的執行緒則執行任務,若無則不建立執行緒。並且每一個空閒執行緒會在60秒後自動回收。 4.newScheduledThreadPool()方法,該方法返回一個SchededExecutorService物件,但該執行緒池可以指定執行緒的數量。
- 注:以上4中方法的本質內部底層都是實際建立的都是一個ThreadPoolExecutor物件,只是對ThreadPoolExecutor構造方法,進行了預設值的設定。
原始碼解讀 |
---|
- 因此,在以上方法不足以供我們使用時,可以自己定義執行緒池,構造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {…}
- corePoolSize 核心執行緒數(表示執行緒池初始化的時候就存在多少個執行緒);
- maximumPoolSize 執行緒池最大容量大小;
- keepAliveTime 執行緒池空閒時,執行緒存活的時間;
- TimeUnit 時間單位;
- ThreadFactory 執行緒工廠;
- BlockingQueue任務佇列(執行緒數大於執行緒池中執行緒的數量釋出放入的佇列);
- RejectedExecutionHandler 執行緒拒絕策略;(例如執行緒池中有兩個執行緒,若這兩個執行緒都被佔用第3個執行緒來了可以設定拒絕策略拒絕這個執行緒)
2.1 newCachedThreadPool(實現定時任務)
package com.rrss.test.thread;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
class Task extends Thread {
public void run() {
System.out.println("run");
}
}
public class ThreadPoolDemo {
public static void main(String[] args) {
Task task = new Task();
ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);
scheduled.scheduleWithFixedDelay(task, 3, 1, TimeUnit.SECONDS);// task在啟動3s後,每隔1秒執行