1. 程式人生 > >JDK執行緒池簡介與使用

JDK執行緒池簡介與使用


一、執行緒池簡介

  • 為了避免系統頻繁的建立和銷燬執行緒,我們可以將建立的執行緒進行復用。資料庫中的資料庫連線池也是此意。Java中的執行緒池是運用場景最多的併發框架,幾乎所有需要非同步或併發執行任務的程式都可以使用執行緒池。在開發過程中,合理地使用執行緒池能夠帶來以下好處:
  1. 第一:降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。
  2. 第二:提高響應速度。當任務到達時,任務可以不需要等到執行緒建立就能立即執行。
  3. 第三:提高執行緒的可管理性。執行緒是稀缺資源,如果無限制地建立,不僅會消耗系統資源,還會降低系統的穩定性,使用執行緒池可以進行統一分配、調優和監控。但是,要做到合理利用執行緒池,必須對其實現原理了如指掌。
  • 線上程池中總有那麼幾個活躍的執行緒,也有一定的最大值限制,一個業務使用完執行緒之後,不是立即銷燬而是將其放入到執行緒池中,從而實現執行緒的複用。簡而言之:建立執行緒變成了從執行緒池獲取空閒的執行緒,關閉執行緒變成了向池子中歸還執行緒。

二、JDK對執行緒池的支援

  • 為了更好的控制多執行緒,JDK提供了一套執行緒框架Executor,幫助開發人員有效的進行執行緒控制。他們都在java.util.concurrent包中,時JDK併發包的核心。其中一個比較重要的類:Executors,扮演者執行緒工廠的角色,我們通過Executors可以建立特定功能的執行緒池。 Executors建立執行緒池的方法:
  1. newFixedThreadPool()方法,該方法返回一個固定數量的執行緒池,該方法的執行緒數始終不變,當有一個任務提交時,若執行緒池中空閒,則立即執行,若沒有,則會被暫緩在一個任務佇列中等待有空閒的執行緒去執行。
  2. newSingleThreadExecutor()方法,建立一個執行緒的執行緒池,若空閒則執行,若沒有空閒則暫緩在任務佇列中。
  3. newCachedThreadPool()方法,返回一個可根據實際情況調整執行緒個數的執行緒池,不限制最大執行緒數量,若用空閒的執行緒則執行任務,若無則不建立執行緒。並且每一個空閒執行緒會在60秒後自動回收。 4.newScheduledThreadPool()方法,該方法返回一個SchededExecutorService物件,但該執行緒池可以指定執行緒的數量。
  • 注:以上4中方法的本質內部底層都是實際建立的都是一個ThreadPoolExecutor物件,只是對ThreadPoolExecutor構造方法,進行了預設值的設定。
原始碼解讀
  • 因此,在以上方法不足以供我們使用時,可以自己定義執行緒池,構造方法如下:
public ThreadPoolExecutor(int corePoolSize, 
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {…}

  1. corePoolSize 核心執行緒數(表示執行緒池初始化的時候就存在多少個執行緒);
  2. maximumPoolSize 執行緒池最大容量大小;
  3. keepAliveTime 執行緒池空閒時,執行緒存活的時間;
  4. TimeUnit 時間單位;
  5. ThreadFactory 執行緒工廠;
  6. BlockingQueue任務佇列(執行緒數大於執行緒池中執行緒的數量釋出放入的佇列);
  7. 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秒執行