多線程 - 線程池的實現

概述


系統啓動一個新線程的成本是比較高的,因爲它需要與系統交互,使用線程池可以有效地控制系統中併發線程的數量。尤其是當系統中需要創建大量生命週期很短的線程時,這種效果尤爲明顯。
線程池會在程序啓動時創建一定數量的線程。當程序將一個Runnable對象或Callable對象傳給線程池,線程池會啓動一個線程來執行它的run()方法或call()方法。當run()方法或call()方法執行結束後,該線程不會立刻死亡,而是再次返回線程池中成爲空閒狀態,等待執行下一個任務。

API


從Java 5以後,JDK新增了一個Executors工廠類來創建線程池,該工廠類包含如下幾個靜態方法:
  • newCachedThreadPool():創建一個具有緩衝功能的線程池,系統根據需要創建線程,這些線程將會被緩存在線程池中。
  • newFixedThreadPool(int nThreads):創建一個可重用、具有固定線程數的線程池。
  • newSingleThreadExecutor():創建一個只有一個線程的線程池。
  • newScheduledThreadPool(int corePoolSize):創建具有指定線程數的線程池,它可以在指定延遲後執行任務。corePoolSize指線程池中所保存的線程數,即使線程是空閒的也被保存在線程池內。
  • newSingleThreadScheduledExecutor():創建只有一個線程的線程池,它可以在指定延遲後執行任務。
前3個方法返回一個ExecutorService對象,它代表線程池,可以執行Runnable或Callable任務。後2個方法返回一個ScheduledExecutorService對象,它是ExecutorService的子類,在指定延遲後執行線程任務。ExecutorService提供了3個方法來執行線程任務:
  • Future<?> submit(Runnable task):將一個Runnable任務提交給線程池,線程池將在有空閒線程是執行Runnable任務。Future對象代表Runnable任務的返回值——run()方法沒有返回值,將返回null。
  • <T> Future<T> submit(Runnable task, T result):將一個Runnable任務提交給線程池,線程池將在有空閒線程是執行Runnable任務。其中result表示返回值,線程執行結束後返回result。
  • <T> Future<T> submit(Callable<T> task):將一個Callable任務提交給線程池,線程池將在有空閒線程是執行Callable任務。Future對象代表Callable任務的返回值。
當執行完線程任務後,應該關閉線程池。調用shutdown()方法後,線程池將不再接收新的線程任務,並將所有正在執行的線程任務執行完畢後關閉線程池。shutdownNow()方法會停止所有正在執行的線程任務並關閉線程池。

代碼示例


使用線程池來執行線程任務的步驟如下:
(1)調用Executors類的靜態工廠方法創建一個ExecutorService對象,該對象代表一個線程池;
(2)創建Runnable實現類或Callable實現類的實例,作爲線程任務;
(3)調用ExecutorService對象的submit()方法來提交線程任務;
(4)線程任務執行完畢後,關閉線程池。

package Demo;

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

class MyTask implements Runnable {
    @Override
    public void run() {
	for (int i = 0; i < 100; i++) {
	    System.out.println(Thread.currentThread().getName() + "的i值爲" + i);
	}
    }
}

public class ThreadPoolDemo {

    public static void main(String[] args) {
	// 創建線程池,容量爲4
	ExecutorService threadPool = Executors.newFixedThreadPool(4);
	// 提交三個線程任務
	threadPool.submit(new MyTask());
	threadPool.submit(new MyTask());
	threadPool.submit(new MyTask());
	// 關閉線程池
	threadPool.shutdown();
    }
}
測試結果:
pool-1-thread-1的i值爲0
pool-1-thread-2的i值爲0
pool-1-thread-2的i值爲1
pool-1-thread-2的i值爲2
pool-1-thread-3的i值爲0
pool-1-thread-2的i值爲3
pool-1-thread-1的i值爲1
pool-1-thread-2的i值爲4
pool-1-thread-2的i值爲5
pool-1-thread-2的i值爲6
pool-1-thread-3的i值爲1
pool-1-thread-2的i值爲7
pool-1-thread-2的i值爲8
pool-1-thread-2的i值爲9
pool-1-thread-2的i值爲10
pool-1-thread-2的i值爲11
pool-1-thread-2的i值爲12
pool-1-thread-2的i值爲13
......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章