Android之線程池深度剖析
1.線程池的引入 引入的好處: 1)提升效能。建立和消耗對象費時費CPU資源 2)防止記憶體過度消耗。控制活動線程的數量,防止並發線程過多。 使用條件: 假設在一台伺服器完成一項任務的時間為T T1 建立線程的時間 T2 線上程中執行任務的時間,包括線程間同步所需時間 T3 線程銷毀的時間 顯然T = T1+T2+T3。注意這是一個極度簡化的假設。 可以看出T1,T3是多線程本身的帶來的開銷,我們渴望減少T1,T3所用的時間,從而減少T的時間。但一些線程的使用者並沒有注意到這一點,所以在程式中頻繁的建立或銷毀線程,這導致T1和T3在T中佔有相當比例。顯然這是突出了線程的弱點(T1,T3),而不是優點(並發性)。 線程池技術正是關注如何縮短或調整T1,T3時間的技術,從而提高伺服器程式效能的。它把T1,T3分別安排在伺服器程式的啟動和結束的時間段或者一些閒置時間段,這樣在伺服器程式處理客戶請求時,不會有T1,T3的開銷了。 線程池不僅調整T1,T3產生的時間段,而且它還顯著減少了建立線程的數目。 在Android中當同時並發多個網路線程時,引入線程池技術會極大地提高APP的效能。 2.線程池例子 1)JDK自身帶有線程池的實作類別ThreadPoolExecutor 2)下面是一個類比ThreadPoolExecutor的例子,以加深對原理的理解 複製代碼public final class ThreadPool { // 線程池中預設線程的個數為5 private static int worker_num = 5; // 背景工作執行緒 private WorkThread[] workThreads; // 任務隊列,作為一個緩衝,List線程不安全 private List<Runnable> taskQueue = new LinkedList<Runnable>(); private static ThreadPool threadPool; // 建立具有預設線程個數的線程池 private ThreadPool() { this(5); } // 建立線程池,worker_num為線程池中背景工作執行緒的個數 private ThreadPool(int worker_num) { ThreadPool.worker_num = worker_num; workThreads = new WorkThread[worker_num]; for (int i = 0; i < worker_num; i++) { workThreads[i] = new WorkThread(); workThreads[i].start();// 開啟線程池中的線程 } } // 單態模式,獲得一個預設線程個數的線程池 public static ThreadPool getThreadPool() { return getThreadPool(ThreadPool.worker_num); } // 單態模式,獲得一個指定線程個數的線程池,worker_num(>0)為線程池中背景工作執行緒的個數 // worker_num<=0建立預設的背景工作執行緒個數 public static ThreadPool getThreadPool(int worker_num1) { if (threadPool == null) threadPool = new ThreadPool(worker_num1); return threadPool; } // 執行任務,其實只是把任務加入任務隊列,什麼時候執行有線程池管理器覺定 public void addTask(Runnable task) { synchronized (taskQueue) { taskQueue.add(task); taskQueue. notifyAll(); } } // 銷毀線程池,該方法保證在所有任務都完成的情況下才銷毀所有線程,否則等待任務完成才銷毀 public void destroy() { while (!taskQueue.isEmpty()) {// 如果還有任務沒執行完成,就先睡會吧 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } // 背景工作執行緒停止工作,且置為null for (int i = 0; i < worker_num; i++) { workThreads[i].stopWorker(); workThreads[i] = null; } threadPool=null; taskQueue.clear();// 清空任務隊列 } /** * 內部類,背景工作執行緒 */ private class WorkThread extends Thread { // 該背景工作執行緒是否有效,用於結束該背景工作執行緒 private boolean isRunning = true; /* * 關鍵所在啊,如果任務隊列不空,則取出任務執行,若任務隊列空,則等待 */ @Override public void run() { Runnable r = null; while (isRunning) {// 注意,若線程無效則自然結束run方法,該線程就沒用了 synchronized (taskQueue) { while (isRunning && taskQueue.isEmpty()) {// 隊列為空白 try { taskQueue.wait(20); } catch (InterruptedException e) { e.printStackTrace(); } } if (!taskQueue.isEmpty()) r = taskQueue.remove(0);// 取出任務 } if (r != null) { r.run();// 執行任務 } r = null; } } // 停止工作,讓該線程自然執行完run方法,自然結束 public void stopWorker() { isRunning = false; } }}