使用執行緒池優化多執行緒程式設計

sanqima發表於2014-06-05

   Java中的物件是使用new操作符建立的,如果建立大量短生命週期的物件,這種方式效能非常低下。為了解決這個問題,而發明了池技術。

對於資料庫連線有連線池,對於執行緒則有執行緒池。

本例項介紹兩種方式建立1000個短生命週期的執行緒,第一種是普通方式,第二種是執行緒池的方式。通過時間和記憶體消耗的對比,就可以很明顯地看出執行緒池的優勢。

例項結果如下:

說明:使用執行緒池建立物件的時間是15毫秒,說明執行緒池是非常高效的。

關鍵技術:

     Executors類為java.util.concurrent包中所定義的Executor、ExecutorService、ScheduleExecutorService、ThreadFactory和Callable類提供工廠方法和實用方法。該類支援以下各種方法:

 (a)建立並返回設定有常用配置字串的ExecutorService方法。

 (b)建立並返回設定有常用配置字串的ScheduleService方法。

 (c)建立並返回“包裝的”ExecutorService方法,它通過使特定於實現的方法不可訪問來禁用 重新配置。

 (d)建立並返回ThreadFactory方法,它可以將建立的執行緒設定為已知的狀態。

 (e)建立並返回非閉包形式的Callable方法,這樣可將其用於需要Callable的執行方法中。

    本例項使用newFixedThreadPool()方法,建立一個可重用固定執行緒數的執行緒池,它以共享的無界佇列方式來執行這些執行緒。該方法的宣告如下:

        public static ExecutorService newFixedThreadPool(int nThreads)

    引數說明: nThreads為池中的執行緒池。

設計過程:

  1)編寫類TempThread,該類實現了Runnable介面。在run()方法中,進行簡單的自增運算,程式碼如下:

public class TempThread implements Runnable {// 測試用的Runnable介面實現類
    private int id = 0;
    
    @Override
    public void run() {// run()方法給id做自增運算
        id++;
    }
}

  2)編寫類ThreadPoolTest進行測試,在main()方法中,使用兩種方式建立1000個執行緒,分別輸出了建立時間和佔用的記憶體。程式碼如下:

</pre><pre class="java" name="code">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolTest {
    public static void main(String[] args) {
        Runtime run = Runtime.getRuntime();// 建立Runtime物件
        run.gc();// 執行垃圾回收器,這樣可以減少誤差
        long freeMemory = run.freeMemory();// 獲得當前虛擬機器的空閒記憶體
        long currentTime = System.currentTimeMillis();// 獲得當前虛擬機器的時間
        for (int i = 0; i < 10000; i++) {// 獨立執行1000個執行緒
            new Thread(new TempThread()).start();
        }
        System.out.println("獨立執行1000個執行緒所佔用的記憶體:" + (freeMemory - run.freeMemory()) + "位元組");// 檢視記憶體的變化
        System.out.println("獨立建立1000個執行緒所消耗的時間:" + (System.currentTimeMillis() - currentTime) + "毫秒");// 檢視時間的變化
        
        run.gc();// 執行垃圾回收器
        freeMemory = run.freeMemory();// 獲得當前虛擬機器的空閒記憶體
        currentTime = System.currentTimeMillis();// 獲得當前虛擬機器的時間
        ExecutorService executorService = Executors.newFixedThreadPool(2);// 建立執行緒池
        for (int i = 0; i < 1000; i++) {// 使用執行緒池執行1000個執行緒
            executorService.submit(new TempThread());
        }
        System.out.println("使用連線池執行1000個執行緒所佔用的記憶體:" + (freeMemory - run.freeMemory()) + "位元組");// 檢視記憶體的變化
        System.out.println("使用連線池建立1000個執行緒所消耗的時間:" + (System.currentTimeMillis() - currentTime) + "毫秒");// 檢視時間的變化
    }
}

注意:在使用完執行緒池後,需要呼叫ExecutorService介面中定義的shutdownNow()方法,來終止執行緒池。


 

 

 

相關文章