1. 程式人生 > >*Android 多執行緒下載 仿下載助手

*Android 多執行緒下載 仿下載助手

今天帶來一個多執行緒下載的 例子。先看一下效果,點選 下載 開始下載,同時顯示下載進度,下載完成,變成程 安裝,點選安裝 提示 安裝應用。

介面效果

這裡寫圖片描述

執行緒池 ThreadPoolExecutor

在下面介紹實現下載原理的時候,我想嘗試倒著來說,這樣是否好理解一點? 
我們都知道,下載助手,比如360, 百度的 手機助手,下載APP 的時候 ,都可以同時下載多個,所以,下載肯定是多執行緒的,所以我們就需要一個執行緒工具類 來管理我們的執行緒,這個工具類的核心,就是 執行緒池。 
執行緒池ThreadPoolExecutor ,先簡單學習下這個執行緒池的使用

  1. /** 
  2.        * Parameters: 
  3.           corePoolSize 
     
  4.              the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set 
  5.           maximumPoolSize  
  6.               the maximum number of threads to allow in the pool 
  7.           keepAliveTime 
  8.               when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
     
  9.           unit  
  10.               the time unit for the keepAliveTime argument 
  11.           workQueue  
  12.               the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted                   by the execute method. 
  13.           handler  
  14.              the handler to use when execution is blocked because the thread bounds and queue capacities are reached
     
  15.         Throws: 
  16.           IllegalArgumentException - if one of the following holds: 
  17.           corePoolSize < 0 
  18.           keepAliveTime < 0 
  19.           maximumPoolSize <= 0 
  20.           maximumPoolSize < corePoolSize 
  21.           NullPointerException - if workQueue or handler is null 
  22.        */
  23.       ThreadPoolExecutor threadpool=new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler)  

上面是 ThreadPoolExecutor的引數介紹, 

第一個引數 corePoolSize : 空閒時 存在的執行緒數目、 
第二個引數 maximumPoolSize :允許同時存在的最大執行緒數、 
第三個引數 keepAliveTime: 這個引數是 允許空閒執行緒存活的時間、 
第四個引數 unit : 是 時間的單位 、 
第五個引數 workQueue :這個是一個容器,它裡面存放的是、 threadpool.execute(new Runnable()) 執行的執行緒.new Runnable()、 
第六個引數 handler:當執行被阻塞時,該處理程式將被阻塞,因為執行緒的邊界和佇列容量達到了 。

工具類 ThreadManager

介紹完了 執行緒池引數,那我們就先建立一個執行緒管理的工具類 ThreadManager

  1. publicclass ThreadManager {  
  2.     publicstaticfinal String DEFAULT_SINGLE_POOL_NAME = "DEFAULT_SINGLE_POOL_NAME";  
  3.     privatestatic ThreadPoolProxy mLongPool = null;  
  4.     privatestatic Object mLongLock = new Object();  
  5.     privatestatic ThreadPoolProxy mShortPool = null;  
  6.     privatestatic Object mShortLock = new Object();  
  7.     privatestatic ThreadPoolProxy mDownloadPool = null;  
  8.     privatestatic Object mDownloadLock = new Object();  
  9.     privatestatic Map<String, ThreadPoolProxy> mMap = new HashMap<String, ThreadPoolProxy>();  
  10.     privatestatic Object mSingleLock = new Object();  
  11.     /** 獲取下載執行緒 */
  12.     publicstatic ThreadPoolProxy getDownloadPool() {  
  13.         synchronized (mDownloadLock) {  
  14.             if (mDownloadPool == null) {  
  15.                 mDownloadPool = new ThreadPoolProxy(33, 5L);  
  16.             }  
  17.             return mDownloadPool;  
  18.         }  
  19.     }  
  20.     /** 獲取一個用於執行長耗時任務的執行緒池,避免和短耗時任務處在同一個佇列而阻塞了重要的短耗時任務,通常用來聯網操作 */
  21.     publicstatic ThreadPoolProxy getLongPool() {  
  22.         synchronized (mLongLock) {  
  23.             if (mLongPool == null) {  
  24.                 mLongPool = new ThreadPoolProxy(55, 5L);  
  25.             }  
  26.             return mLongPool;  
  27.         }  
  28.     }  
  29.     /** 獲取一個用於執行短耗時任務的執行緒池,避免因為和耗時長的任務處在同一個佇列而長時間得不到執行,通常用來執行本地的IO/SQL */
  30.     publicstatic ThreadPoolProxy getShortPool() {  
  31.         synchronized (mShortLock) {  
  32.             if (mShortPool == null) {  
  33.                 mShortPool = new ThreadPoolProxy(22, 5L);  
  34.             }  
  35.             return mShortPool;  
  36.         }  
  37.     }  
  38.     /** 獲取一個單執行緒池,所有任務將會被按照加入的順序執行,免除了同步開銷的問題 */
  39.     publicstatic ThreadPoolProxy getSinglePool() {  
  40.         return getSinglePool(DEFAULT_SINGLE_POOL_NAME);  
  41.     }  
  42.     /** 獲取一個單執行緒池,所有任務將會被按照加入的順序執行,免除了同步開銷的問題 */
  43.     publicstatic ThreadPoolProxy getSinglePool(String name) {  
  44.         synchronized (mSingleLock) {  
  45.             ThreadPoolProxy singlePool = mMap.get(name);  
  46.             if (singlePool == null) {  
  47.                 singlePool = new ThreadPoolProxy(11, 5L);  
  48.                 mMap.put(name, singlePool);  
  49.             }  
  50.             return singlePool;  
  51.         }  
  52.     }  
  53.     publicstaticclass ThreadPoolProxy {  
  54.         private ThreadPoolExecutor mPool;  
  55.         privateint mCorePoolSize;  
  56.         privateint mMaximumPoolSize;  
  57.         privatelong mKeepAliveTime;  
  58.         private ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {  
  59.             mCorePoolSize = corePoolSize;  
  60.             mMaximumPoolSize = maximumPoolSize;  
  61.             mKeepAliveTime = keepAliveTime;  
  62.         }  
  63.         /** 執行任務,當執行緒池處於關閉,將會重新建立新的執行緒池 */
  64.         publicsynchronizedvoid execute(Runnable run) {  
  65.             if (run == null) {  
  66.                 return;  
  67.             }  
  68.             if (mPool == null || mPool.isShutdown()) {  
  69.                 mPool = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.MILLISECONDS, new