天天看點

Java并發程式設計詳解線程的基礎知識線程池Callable和Future以及FutureTask的執行個體應用

關于線程的基礎知識,比如線程的建立(thread,runnable),程序和線程的差別,以及線程的sleep、synchronized、wait、interrupt、join、yield等方法就不詳細講解了。有需要的可以參考海子大神的文章。

建立線程池

在java doc中,并不提倡我們直接使用threadpoolexecutor,而是使用executors類中提供的幾個靜态方法來建立線程池:

<a></a>

線程池的使用

在工作中如何設定線程池的大小呢?

設定線程池的大小

線程池的理想大小取決于被送出任務的類型以及所部署系統的特性。在代碼中通常不會固定線程池的大小,而應該通過某種配置機制來提供,或者根據runtime.availableprocessors來動态計算。

幸運的是,要設定線程池的大小也并不困難,隻需要避免“過大”和“過小”這兩種極端情況。如果線程池過大,那麼大量的線程将在相對很少的cpu和記憶體資源上發生競争,這不僅會導緻更高的記憶體使用量,而且還可能耗盡資源。如果線程池過小,那麼将導緻許多空間的處理器無法執行工作,進而降低吞吐率。

要想正确地設定線程池的大小,必須分析計算環境、資源預算和任務的特性。在部署的系統中有多少個cpu?多大的記憶體?任務是計算密集型、i/o密集型還是二者皆可?它們是否需要像jdbc連接配接這樣的稀缺資源?如果需要執行不同類别的任務,并且它們之間的行為相差很大,那麼應該考慮使用多個線程池,進而使每個線程池可以根據各自的工作負載來調整。

對于計算密集型的任務,在擁有ncpu個處理器的系統上,當線程池的大小為 ncpu+1 時,通常能實作最優的使用率。

線程池的最優大小等于:

給定下列定義:

ncpu是cpu的數目,一般可以通過這個公式擷取 int n_cpus = runtime.getruntime().availableprocessors() ucpu:cpu的使用率,範圍為 0&lt;=ucpu&lt;=1 w/c:是等待時間和計算時間的比值

一般需要根據任務的類型來配置線程池大小:

  如果是cpu密集型任務,就需要盡量壓榨cpu,參考值可以設為 ncpu+1

  如果是io密集型任務,參考值可以設定為2*ncpu

  當然,這隻是一個參考值,具體的設定還需要根據實際情況進行調整,比如可以先将線程池大小設定為參考值,再觀察任務運作情況和系統負載、資源使用率來進行适當調整。

  

    有的時候我們的應用需要拿到線程執行完畢後的傳回值,這個時候就需要用到callable和future以及futuretask了。下面是一個執行個體,copy就可以運作,也可以看執行個體有詳細注釋說明。