大文件 and 多下载任务的封装(一)---线程池的封装(ThreadPool,TheadManager)

ThreadManager

原文地址
大文件 and 多下载任务的封装二
大文件 and 多下载任务的封装三·

前段时间对三级缓存机制做了系统的分析,但是对于网络下载的问题还有很多,比如今天遇到的问题,针对一些需要下载大文件,并且需要进行多线程下载的应用来说,(比如,像一些应用商店,软件的下载和一些累似的多线程的下载类型)就需要用到线程池,下载就简单介绍对线程池的封装

一.为什么要使用线程池

根据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(), 
                        //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(), 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(), Executors.defaultThreadFactory(),
                        new ThreadPoolExecutor.AbortPolicy());
            }
            if(executor != null){

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

你可能感兴趣的:(Android)