Android中的多线程处理(一)——线程任务管理器

线程任务管理器的目的是为了在系统资源可用时自动运行线程任务或同时执行多个线程任务。Android API提供了ThreadPoolExecutor类,它管理了一个线程池,当线程池中的某个线程可用时它会从任务队列中取出一个任务来运行,我们需要做的就是把我们要执行的任务放入它的任务队列中。ThreadPoolExecutor可以同时并行执行一个任务,因此我们必须要确保我们的执行任务是线程安全的。

如何使用ThreadPoolExecutor

在线程任务管理器中实例化ThreadPoolExecutor,并声明一个静态引用指向它。尽管线程任务管理器可能需要执行不同类型的线程任务,但管理器本身只需要一个单实例即可,因此我们可以把管理器类定义为单实例类并在静态初始化块中进行实例化,下面为一个完整的示例:

public class PhotoManager

 {

    ...
    /*
     * 获取系统可用的CPU核数,基于此来对线程池的线程数量进行设置
     * 需要注意的是,该值可能并非系统的实际CPU核数,因为某些系统
     * 可能会根据系统的负载来动态调整可用的CPU,availableProcessors()
     * 方法返回的就是当前活跃的CPU核数,该值可能小于系统总的核数
     */
    private static int NUMBER_OF_CORES =
            Runtime.getRuntime().availableProcessors();
    ...
    //声明一个任务队列
    private final BlockingQueue<Runnable> mDecodeWorkQueue;
    ...
    //设置一个线程可闲置的时间
    private static final int KEEP_ALIVE_TIME = 1;
    //设置一个线程可闲置的时间的单位
    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
    ...
    static  {
        ...
        // 创建线程任务管理器PhotoManager类的静态单实例
        sInstance = new PhotoManager();
    }
    ...
    /**
     * 在这里创建任务队列和线程池 
     */
    private PhotoManager() {
        ...
        //任务队列的数据结构为LinkedBlockingQueue,ThreadPoolExecutor从这里取出
        //一个执行任务交给线程池中的一个线程来执行,该队列通常为一个FIFO先入先出
        //的队列,我们可以使用BlockingQueue接口的任何实现类
        mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();
        ...
        // 创建一个线程池
        mDecodeThreadPool = new ThreadPoolExecutor(
            NUMBER_OF_CORES,       // 线程池的初始线程数量
            NUMBER_OF_CORES,       // 线程池的最大线程数量
            KEEP_ALIVE_TIME,
            KEEP_ALIVE_TIME_UNIT,
            mDecodeWorkQueue);
        ...
        // 初始化一个Handler对象来处理界面的刷新
        mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message inputMessage) {
                ...
                //根据收到的消息来进行界面的刷新
                ...
            }
            ...
        }
    }
    ...
    // 线程任务启动方法
    public static PhotoTask startDownload(PhotoView imageView,
        boolean cacheFlag) {
        ...
        // 使用线程池来执行线程任务
        sInstance.
                mDownloadThreadPool.
                execute(downloadTask.getHTTPDownloadRunnable());
        ...
    }

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。