1. 程式人生 > >大檔案 and 多下載任務的封裝(一)---執行緒池的封裝(ThreadPool,TheadManager)

大檔案 and 多下載任務的封裝(一)---執行緒池的封裝(ThreadPool,TheadManager)

ThreadManager

前段時間對三級快取機制做了系統的分析,但是對於網路下載的問題還有很多,比如今天遇到的問題,針對一些需要下載大檔案,並且需要進行多執行緒下載的應用來說,(比如,像一些應用商店,軟體的下載和一些累似的多執行緒的下載型別)就需要用到執行緒池,下載就簡單介紹對執行緒池的封裝

一.為什麼要使用執行緒池

根據android單執行緒模式規定,android只允許有一個主執行緒,也就是UI執行緒,一切更新UI的操作必須在UI執行緒中使用,然而對應的一切的耗時操作,只允許在子線稱中執行,所以針對子線稱的下載操作,可以使用執行緒池進行管理,所以封裝執行緒吃對執行緒池管理工具,也是非常實用的。

  1. 提升效能。建立和消耗物件費時,費CPU資源.
  2. 防止記憶體過度消耗。控制活動執行緒的數量,防止併發執行緒過多。
  3. 最大的好處就是,當我們想使用時可以直接新建然後加入執行緒池即可,也可以對執行緒進行復用,當我們不想使用的時候直接就可以把它關閉。

二.為什麼要對執行緒池進行封裝

有的人可能會說, java.util.concurrent.ThreadPoolExecutor;提供了原生的執行緒池,我們為什麼還要對它進行封裝呢?直接使用不就好了,那麼問題來了?

  1. .ThreadPoolExecutor的使用必須保證一個app中只能擁有一個(也就是必須保證單例模式),否則也無法保證子執行緒的數木
  2. 封裝是為了更好的管理執行緒,是為了優化程式碼的使用效率,更好的管理程式碼。

三.執行緒池進行封裝

####(一)原理分析

  1. 首先先看一下ThreadPoolExecutor的引數

/**

    下面對執行緒池的方法引數進行解釋,其餘兩個就不解說了,一些引數使用系統預設的即可,
    Runtime.getRuntime().availableProcessors();進行設定
    對於休息時間,則是為了考慮系統長時間執行而導致的系統發熱現象,
    一般情況下可以選擇為0L
**/

ThreadPoolExecutor  executor = new ThreadPoolExecutor(
                        //1.第一個引數:核心的執行緒數,
corePoolSize, //2.第二個引數,預設使用的最大執行緒數 maximumPoolSize, //3.執行緒執行時的休眠時間的數值, keepAliveTime, //4.執行緒執行時休眠的時間的單位,也就是上一個引數的單位 TimeUnit.SECONDS, //5.執行緒的佇列 new LinkedBlockingQueue<Runnable>(), //6.生產執行緒的工廠 Executors.defaultThreadFactory(), //7.執行緒異常的處理策略 new ThreadPoolExecutor.AbortPolicy() );
  1. 因為執行緒池必須保持一個app中只能有一個例項,所以我們使用單例模式,在這裡可以使用懶漢模式
//這裡使用的是ThreadManager類,把它設定稱單例
//而ThreadPool則是在內部類中引用
  private static ThreadPool Instance;
    //單例模式,獲取執行緒池的例項
    public  static ThreadPool getInstance(){
        if(Instance == null){
            synchronized (ThreadPool.class){
                if(Instance == null){
                    int threadCount = Runtime.getRuntime().availableProcessors();
                    Instance = new ThreadPool(threadCount,threadCount,1L);
                }
            }
        }
        return Instance;
    }
  1. 對與執行緒池來說,我們首先應該有一個向執行緒池中新增執行緒的操作
  public  void execute(Runnable r){
  //當ThreadPoolExecutor為null時才新建一個,否則使用原有的。
            if(executor == null){
                executor = new ThreadPoolExecutor(
                        corePoolSize,maximumPoolSize,keepAliveTime, TimeUnit.SECONDS,
                        new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(),
                        new ThreadPoolExecutor.AbortPolicy());
            }
            if(executor != null){
//如果不為空,那麼就直接執行此子線稱
                executor.execute(r);
            }
        }
  1. 當我們對已經開始下載的執行緒突然不想下載了,或者點錯了,那麼就需要取消執行緒
//在這裡我們只需要把執行緒從執行緒池中移除
 public void cancel(Runnable r){
            if(executor != null){
            //雖然已經移除了,但是下載還是正在執行的,所以我們應該在子線稱動態新增取消事件,進行取消
                executor.getQueue().remove(r);
            }
        }
  1. 為了防止ThreadManager被直接new出物件,所以應該對構造方法進行限制
private Thread<Manager(){
}

四.ThreadManager的使用

//這裡是簡單的使用

Runnable r = new Runnable(){

}
ThreadManager.getInstance().execute(r);

五.程式碼

package com.example.orchid.googleplatstore.manager;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by orchid
 * on 16-11-4.
 *  執行緒池類的封裝
 *
 */

public class ThreadManager {

    private static ThreadPool Instance;

    //單例模式,獲取執行緒池的例項
    public  static ThreadPool getInstance(){
        if(Instance == null){
            synchronized (ThreadPool.class){
                if(Instance == null){
                    int threadCount = Runtime.getRuntime().availableProcessors();
                    Instance = new ThreadPool(threadCount,threadCount,1L);
                }
            }
        }
        return Instance;
    }


    public static class ThreadPool{

        private  ThreadPoolExecutor executor;
        private  int corePoolSize;
        private  int maximumPoolSize;
        private  long keepAliveTime;

        public ThreadPool(int corePoolSize,int maximumPoolSize,long keepAliveTime) {
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.keepAliveTime = keepAliveTime;
        }

        public  void execute(Runnable r){
            if(executor == null){

                //執行緒池執行者。
                //參1:核心執行緒數;參2:最大執行緒數;參3:執行緒休眠時間;參4:時間單位;參5:執行緒佇列;參6:生產執行緒的工廠;參7:執行緒異常處理策略
                executor = new ThreadPoolExecutor(
                        corePoolSize,maximumPoolSize,keepAliveTime, TimeUnit.SECONDS,
                        new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(),
                        new ThreadPoolExecutor.AbortPolicy());
            }
            if(executor != null){

                executor.execute(r);
            }
        }
        //取消執行緒
        public void cancel(Runnable r){
            if(executor != null){
                executor.getQueue().remove(r);
            }
        }
    }
}