广

android开发

  • IOS开发
  • android开发
  • PHP编程
  • JavaScript
  • ASP.NET
  • ASP编程
  • JSP编程
  • Java编程
  • 易语言
  • Ruby编程
  • Perl编程
  • AJAX
  • 正则表达式
  • C语言
  • 编程开发

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

    2018-04-09 07:41:45 次阅读 稿源:互联网
    广告

    如果你要反复执行一个任务,用不同的数据集(参数不同),但一次只要一个执行(任务是单线程的),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);
        }

    一起学吧部分文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与一起学吧进行文章共享合作。

    广告
    广告
    广告