昨天我們在BLOG中討論了最常用到的創建線程方法,介紹了他們的用法,優點以及他們的不足之處。當然,我們介紹的兩種方法都不是創建線程的最完美方法,方法一無法并發的處理多個任務,而方法二的話在CPU處理的界限內可以很好的完成任務,但是一旦超出CPU所能承受的壓力,就會導致程序莫名的死掉,所以我們的目標是創建安全的,可使用的,以及高效的線程。
線程池:線程池是指管理線程的同構池,他可以持有所有等待執行的任務,從隊例中獲取下一個任務,執行,然后回來繼續等待另一個線程。和第二種方法比線程池有什么優勢呢?
1. 他重用存在的線程,而不是創建新的線程,這樣做的好處是,在請求到達時,工作線程存在,用于創建線程的等待時間并不會延遲任務的執行,響應性提高了。
2. 通過調整線程池的大小,可以防止過多的線程被創建,不會過多的浪費資源。
所以,使用線程池是使用線程的最明智選擇,只有當CPU和內存資源使用處理一個穩定階段時,我們也才有機會去做調優,管理,監視,記錄日志等其他事情。
今天我們介紹第三種方法:利用線程池(Thread pool),當然我們這里說的線程池并不需要我們自已去實現或者找第三方的實現。在我們使用JDK1.5開發時,Sun已經幫我們寫好,我們需要學的就是如何去合理的使用以及調用他們了。也就是java.util.concurrent下面的接口Executor.
我們先看看API中關于Executor的使用說明:
? 執行已提交的 Runnable 任務的對象。此接口提供一種將任務提交與每個任務將如何運行的機制(包括線程使用的細節、調度等)分離開來的方法。通常使用 Executor 而不是顯式地創建線程
具體如何使用Executor接口呢?下面我們看一個簡單的DEMO:
public class TestExecute {
//設定線程池的大小。大小不空
private static final int NTHREADS=100;
//定義線程池
private static final Executor exec=Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args)throws IOException{
ServerSocket socket=new ServerSocket(80);
while(true){
final Socket connection=socket.accept();
Runnable task=new Runnable(){
public void run(){
//handlerequest(conntection)
}
};
exec.execute(task);
}
}
}
從上面的代碼我們可以看到,在main方法里面其他沒有什么不同,就是最后一步,exec.execute(task),將這個要執行的線程放入自已的線程池中,當然然后執行的方法就是用的JAVA線程池作者的策略來執行了。我們不知道他何時執行開始,何時執行結束,但是有一點可以確定,線程池可以更好的優化程序的速度以及效率。
不過,使用Executor的類必須實現Runnable接口,然爾大家都知道如果是使實Runnable的類執行run() 方法,不能返回值當然也無法拋出已檢查異常。當然,用Executor可以有辦法得到返回值和拋出已檢查異常。
-----------------------------------
Q9原創。