使用線程池優化多線程編程
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()方法,來終止線程池。
使用線程池優化多線程編程