欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android中创建多线程管理器实例

程序员文章站 2022-05-27 10:24:33
如果你要反复执行一个任务,用不同的数据集(参数不同),但一次只要一个执行(任务是单线程的),intentservice符合你的需求。当需要在资源可用时自动执行任务,或允许多...

如果你要反复执行一个任务,用不同的数据集(参数不同),但一次只要一个执行(任务是单线程的),intentservice符合你的需求。当需要在资源可用时自动执行任务,或允许多任务同时执行,你需要一个线程管理器管理你的线程。threadpoolexecutor,会维护一个队列,当它的线程池有空时,从队列里取任务,并执行。要运行任务,你要做的就是把它加到队列里。

线程池可以并联运行一个任务的多个实例,所以你要保存代码线程安全。能被多线程访问的变量需要同步块.更多信息,见processes and threads(http://developer.android.com/guide/components/processes-and-threads.html)

定义线程池类

在它自己类中实例threadpoolexecutor.在类里,如下操作:

为线程池使用static变量

你可能在app里只需要一个单例的线程池,这是为了统一控制限制cpu或网络资源。如果你有不同的runnable类型,你可能想要每种类型都有各自的线程池,但这些都可以放到一个单一的实例里。比如,你可以把它声明成全局变量:

复制代码 代码如下:

public class photomanager {
    ...
    static  {
        ...
        // creates a single static instance of photomanager
        sinstance = new photomanager();
    }
    ...

使用private构造方法

把构造方法声明成private,可以确保单例,这意味着你不需要在同步代码块里封装类访问。

复制代码 代码如下:

 public class photomanager {
        ...
        /**
         * 构建用来下载和decode图片的工作队列和线程池,因为构造方法标记为private,
         * 对其他类不可访问(甚至同包下的类)
         */
        private photomanager() {
            ...
        }

调用线程池类里的方法来开始任务

线程池类里定义一个方法,用来添加任务到线程池队列,如:

复制代码 代码如下:

public class photomanager {
    ...
    // 供photoview调用获取图片
    static public phototask startdownload(
        photoview imageview,
        boolean cacheflag) {
        ...
        // 添加一个任务到线程池
        sinstance.
                mdownloadthreadpool.
                execute(downloadtask.gethttpdownloadrunnable());
        ...
    }

实例化一个ui线程的handler.

handler用于与ui线程通讯,大多数ui控件只允许在ui线程修改。

复制代码 代码如下:

private photomanager() {
    ...
        // defines a handler object that's attached to the ui thread
        mhandler = new handler(looper.getmainlooper()) {
            /*
             * handlemessage() defines the operations to perform when
             * the handler receives a new message to process.
             */
            @override
            public void handlemessage(message inputmessage) {
                ...
            }
        ...
        }
    }

判断线程池参数

一旦你有了全部类结构,你就可以开始定义线程池。实例化一个线程池对象,你需要下面的值:
初始池大小,最大池大小。
线程池的线程数量主要依赖于设备的cpu核心数.可以从系统环境中获取。

复制代码 代码如下:

public class photomanager {
...
    /*
     * gets the number of available cores
     * (not always the same as the maximum number of cores)
     */
    private static int number_of_cores =
            runtime.getruntime().availableprocessors();
}

这个数字可能不能反映出设备的物理cpu内核数量;某些设备cpu会根据系统负载自动禁用部分内核,对于这些设备,availableprocessors()返回的是当前活跃的内核数量。

保持活跃时间和时间单位

一个进程在关闭前,保持空闲状态的时间(可以复用进程)。时间单位在timeunit里

任务队列

threadpoolexecutor的列队保存runnable对象。在线程中执行代码,线程池管理器会从一个fifo队列里取出一个runnable对象,附加到线程里。队列实现blockingqueue接口,在创建线程池时提供。你可以从现有实现中选一个,适应你的需求,参见threadpoolexecutor。下面是使用linkedblockingqueue的例子:

复制代码 代码如下:

public class photomanager {
    ...
    private photomanager() {
        ...
        // a queue of runnables
        private final blockingqueue<runnable> mdecodeworkqueue;
        ...
        // instantiates the queue of runnables as a linkedblockingqueue
        mdecodeworkqueue = new linkedblockingqueue<runnable>();
        ...
    }
    ...
}

创建线程池

调用threadpoolexecutor()方法初始化线程池。它会创建管理线程。因为线程池的初始大小和最大池大小是一样的,threadpoolexecutor在初始化时就创建了所有线程对象,如:

复制代码 代码如下:
    private photomanager() {
        ...
        // sets the amount of time an idle thread waits before terminating
        private static final int keep_alive_time = 1;
        // sets the time unit to seconds
        private static final timeunit keep_alive_time_unit = timeunit.seconds;
        // creates a thread pool manager
        mdecodethreadpool = new threadpoolexecutor(
                number_of_cores,       // initial pool size
                number_of_cores,       // max pool size
                keep_alive_time,
                keep_alive_time_unit,
                mdecodeworkqueue);
    }