*Android 多執行緒下載 仿下載助手
阿新 • • 發佈:2019-02-05
今天帶來一個多執行緒下載的 例子。先看一下效果,點選 下載 開始下載,同時顯示下載進度,下載完成,變成程 安裝,點選安裝 提示 安裝應用。
介面效果
執行緒池 ThreadPoolExecutor
在下面介紹實現下載原理的時候,我想嘗試倒著來說,這樣是否好理解一點?
我們都知道,下載助手,比如360, 百度的 手機助手,下載APP 的時候 ,都可以同時下載多個,所以,下載肯定是多執行緒的,所以我們就需要一個執行緒工具類 來管理我們的執行緒,這個工具類的核心,就是 執行緒池。
執行緒池ThreadPoolExecutor ,先簡單學習下這個執行緒池的使用
- /**
- * Parameters:
- corePoolSize
- the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set
- maximumPoolSize
- the maximum number of threads to allow in the pool
- keepAliveTime
- 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.
- unit
- the time unit for the keepAliveTime argument
- workQueue
- the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
- handler
- the handler to use when execution is blocked because the thread bounds and queue capacities are reached
- Throws:
- IllegalArgumentException - if one of the following holds:
- corePoolSize < 0
- keepAliveTime < 0
- maximumPoolSize <= 0
- maximumPoolSize < corePoolSize
- NullPointerException - if workQueue or handler is null
- */
- 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
- publicclass ThreadManager {
- publicstaticfinal String DEFAULT_SINGLE_POOL_NAME = "DEFAULT_SINGLE_POOL_NAME";
- privatestatic ThreadPoolProxy mLongPool = null;
- privatestatic Object mLongLock = new Object();
- privatestatic ThreadPoolProxy mShortPool = null;
- privatestatic Object mShortLock = new Object();
- privatestatic ThreadPoolProxy mDownloadPool = null;
- privatestatic Object mDownloadLock = new Object();
- privatestatic Map<String, ThreadPoolProxy> mMap = new HashMap<String, ThreadPoolProxy>();
- privatestatic Object mSingleLock = new Object();
- /** 獲取下載執行緒 */
- publicstatic ThreadPoolProxy getDownloadPool() {
- synchronized (mDownloadLock) {
- if (mDownloadPool == null) {
- mDownloadPool = new ThreadPoolProxy(3, 3, 5L);
- }
- return mDownloadPool;
- }
- }
- /** 獲取一個用於執行長耗時任務的執行緒池,避免和短耗時任務處在同一個佇列而阻塞了重要的短耗時任務,通常用來聯網操作 */
- publicstatic ThreadPoolProxy getLongPool() {
- synchronized (mLongLock) {
- if (mLongPool == null) {
- mLongPool = new ThreadPoolProxy(5, 5, 5L);
- }
- return mLongPool;
- }
- }
- /** 獲取一個用於執行短耗時任務的執行緒池,避免因為和耗時長的任務處在同一個佇列而長時間得不到執行,通常用來執行本地的IO/SQL */
- publicstatic ThreadPoolProxy getShortPool() {
- synchronized (mShortLock) {
- if (mShortPool == null) {
- mShortPool = new ThreadPoolProxy(2, 2, 5L);
- }
- return mShortPool;
- }
- }
- /** 獲取一個單執行緒池,所有任務將會被按照加入的順序執行,免除了同步開銷的問題 */
- publicstatic ThreadPoolProxy getSinglePool() {
- return getSinglePool(DEFAULT_SINGLE_POOL_NAME);
- }
- /** 獲取一個單執行緒池,所有任務將會被按照加入的順序執行,免除了同步開銷的問題 */
- publicstatic ThreadPoolProxy getSinglePool(String name) {
- synchronized (mSingleLock) {
- ThreadPoolProxy singlePool = mMap.get(name);
- if (singlePool == null) {
- singlePool = new ThreadPoolProxy(1, 1, 5L);
- mMap.put(name, singlePool);
- }
- return singlePool;
- }
- }
- publicstaticclass ThreadPoolProxy {
- private ThreadPoolExecutor mPool;
- privateint mCorePoolSize;
- privateint mMaximumPoolSize;
- privatelong mKeepAliveTime;
- private ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {
- mCorePoolSize = corePoolSize;
- mMaximumPoolSize = maximumPoolSize;
- mKeepAliveTime = keepAliveTime;
- }
- /** 執行任務,當執行緒池處於關閉,將會重新建立新的執行緒池 */
- publicsynchronizedvoid execute(Runnable run) {
- if (run == null) {
- return;
- }
- if (mPool == null || mPool.isShutdown()) {
- mPool = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.MILLISECONDS, new