線程池

線程池原理:線程池做的工作主要是控制運行的線程的數量,處理過程中將任務放入隊列,然後在線程創建後啓動這些任務,如果線程數量超過了最大數量,超出數量的線程排隊等候,等其它線程執行完畢,再從隊列中取出任務來執行。因此,它有以下幾個主要優點:

提高程序的執行效率:如果程序中有大量短時間任務的線程任務,由於創建和銷燬線程需要和底層操作系統交互,大量時間都耗費在創建和銷燬線程上,因而比較浪費時間,系統效率很低;線程池裏的每一個線程任務結束後,並不會死亡,而是再次回到線程池中成爲空閒狀態,等待下一個對象來使用,因而藉助線程池可以提高程序的執行效率。

控制線程數量,防止程序崩潰:如果不加限制地創建和啓動線程很容易造成程序崩潰,比如高併發1000W個線程,JVM就需要有保存1000W個線程的空間,這樣極易出現內存溢出;線程池中線程數量是一定的,可以有效避免出現內存溢出。

線程複用:每一個 Thread 的類都有一個 start 方法。 當調用 start 啓動線程時 Java 虛擬機會調用該類的 run方法。 那麼該類的 run() 方法中就是調用了 Runnable 對象的 run() 方法。 我們可以繼承重寫Thread 類,在其 start 方法中添加不斷循環調用傳遞過來的 Runnable 對象。 這就是線程池的實現原理。循環方法中不斷獲取 Runnable 是用 Queue 實現的,在獲取下一個 Runnable 之前可以是阻塞的。

線程池的組成
一般的線程池主要分爲以下 4 個組成部分:

1.  線程池管理器:用於創建並管理線程池
2.  工作線程:線程池中的線程
3.  任務接口:每個任務必須實現的接口,用於工作線程調度其運行
4.  任務隊列:用於存放待處理的任務,提供一種緩衝機制

Java 中的線程池是通過 Executor 框架實現的,該框架中用到了 Executor,Executors,ExecutorService,ThreadPoolExecutor ,Callable 和 Future、FutureTask 這幾個類。

在JDK5之前,必須手動才能實現線程池,從JDK5開始新增了一個Executors工廠類,通過該工廠類可以實現線程池,該類有如下常用方法:

public static ExecutorService newCachedThreadPool():創建一個具有緩存功能的線程池,系統根據需要創建線程,這些線程將會被緩存在線程池中;

public static ExecutorService newFixedThreadPool(int nThreads):創建一個可重用的、具有固定線程數的線程池;

public static ExecutorService newSingleThreadExecutor():創建一個只有單線程的線程池,相當於調用newFixedThreadPool(int nThreads)方法時傳入參數爲1。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):創建具有指定線程數的線程池,它可以在指定延遲後執行線程任務。 corePoolSize指池中所保存的線程數,即使線程時空閒的也被保存在線程池內。

public static ScheduledExecutorService newSingleThreadScheduledExecutor():創建只有一個線程的線程池,它可以在指定延遲後執行線程任務。

public static ExecutorService newWorkStealingPool(int parallelism):創建持有足夠的線程的線程池來支持給定的並行級別,該方法還會使用多個隊列來減少競爭。

public static ExecutorService newWorkStealingPool():該方法是前一個方法的簡化版本。如果當前機器有4個CPU,則目標並行級別被設置爲4,也就是相當於爲前一個方法傳入4作爲參數。
基本步驟:創建線程池對象;創建Runable接口實現類實例;提交Runable接口實現類實例;關閉線程池。

測試源碼:

package com.zzu;

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

class CountThread implements Runnable{

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

	public class Test{

	  public static void main(String[] args) {
	    
	    //創建線程池對象,該線程池中有兩個閒置線程
	    ExecutorService pool = Executors.newFixedThreadPool(2);
	    
	    //創建並提交Runable接口實現類實例
	    pool.submit(new CountThread());
	    pool.submit(new CountThread());
	    
	    //關閉線程池
	    pool.shutdown();
	  }
	}

運行結果

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