原文地址:http://android.xsoftlab.net/training/multiple-threads/create-threadpool.html

上节课我们学习了如何定义一个任务。如果只是执行单次任务,那么刚刚所学的已经基本满足要求了。如果需要针对不同的数据执行同种任务,并且需要同一时间只能执行一项任务,那么IntentService可能会适合你。如果要使任务随着资源的可用而执行,或者同一时间需要运行多个任务,那么就需要专门管理这些线程了。Android系统为此提供了一个类,那就是传说中的ThreadPoolExecutor。它可以在线程可用时自动运行队列中的任务。如果要运行一个任务,只需要将任务添加到队列中即可。

ThreadPoolExecutor允许多个线程同时进行,所以应当确保代码是线程安全的。要确保可能会被多个线程访问到的变量被放在同步代码块中。这种方法可以防止一个线程正在读取一个变量的值,而另一个变量正在对这个变量写入新值的现象出现。通常情况下,这种现象会发生在静态变量中,但是也会发生在单例对象上。

定义线程池类

在该类内实例化一个ThreadPoolExecutor对象,并在该类内执行以下工作:

  • 对线程池对象使用静态变量引用

    在APP内通常只需要一个线程池对象的存在:为了对CPU资源或网络资源有一个单一的控制。如果含有不同的Runnable类型,你可能希望对每种类型都创建一个单独线程池,但是每种类型都还是单例类型。在这里的例子中,可以添加以下代码作为全局属性声明。

    public class PhotoManager {...static  {...// Creates a single static instance of PhotoManagersInstance = new PhotoManager();}...
  • 使用私有构造方法:
    私有的构造方法可以确保该类只有一个对象存在。

public class PhotoManager {.../*** Constructs the work queues and thread pools used to download* and decode images. Because the constructor is marked private,* it's unavailable to other classes, even in the same package.*/private PhotoManager() {...}
  • 调用线程池的相关方法启动任务:
    在线程池类内定义一个可以向线程池队列中添加任务的方法。

    public class PhotoManager {...
    // Called by the PhotoView to get a photo
    static public PhotoTask startDownload(PhotoView imageView,boolean cacheFlag) {...// Adds a download task to the thread pool for executionsInstance.mDownloadThreadPool.execute(downloadTask.getHTTPDownloadRunnable());...
    }
  • 在构造方法中实例化一个Handler对象,并将其连接到UI线程:Handler允许安全的调用比如View这种UI对象。大多数的UI对象只允许被UI线程访问。

     private PhotoManager() {
    ...// Defines a Handler object that's attached to the UI threadmHandler = new Handler(Looper.getMainLooper()) {/** handleMessage() defines the operations to perform when* the Handler receives a new Message to process.*/@Overridepublic void handleMessage(Message inputMessage) {...}...}
    }

确定线程池参数

如果要实例化ThreadPoolExecutor对象,需要用到以下值:

线程池的初始值以及最大值:

  • 线程数量的初始值用于指定池子的初始大小,最大值代表了该线程池所允许开放的最大并发数量。线程池中的线程数量取决于设备的可用核心数。这个值与当前的设备颇有关系:
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();
}

这个值可能不能够反映设备的物理核心数量;在一些设备上,核心是否可用取决于系统是否加载。对于这些设备,availableProcessors()返回了当前的活跃核心数量,这个值可能要比真实的总核心数要低。

存活时长及单位

  • 线程在被关闭之间的闲置时长。这个时长由时间单元值负责解释,这些时间单位常量被定义在类TimeUnit中。

任务队列

  • 一个持有Runnable对象的队列。为了启动线程中的执行代码,线程池管理器采用了先进先出的管理原则。在创建线程池之前需要提供一个这样的队列,使用任何实现了BlockingQueue接口的类皆可。为了匹配到APP的要求,你可以选择适当的队列实现;学习更多它们的相关知识,请参见ThreadPoolExecutor的描述文档。这里的使用了LinkedBlockingQueue:
 public class PhotoManager {...private PhotoManager() {...// A queue of Runnablesprivate final BlockingQueue<Runnable> mDecodeWorkQueue;...// Instantiates the queue of Runnables as a LinkedBlockingQueuemDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();...}...
}

线程池创建

创建一个线程池,只需调用ThreadPoolExecutor()实例化一个线程池管理器就好。它会创建并管理一组线程。因为线程池大小的初始值与最大值是相同的,所以ThreadPoolExecutor()会在初始化的时候创建出所指定的线程数量:

    private PhotoManager() {...// Sets the amount of time an idle thread waits before terminatingprivate static final int KEEP_ALIVE_TIME = 1;// Sets the Time Unit to secondsprivate static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;// Creates a thread pool managermDecodeThreadPool = new ThreadPoolExecutor(NUMBER_OF_CORES,       // Initial pool sizeNUMBER_OF_CORES,       // Max pool sizeKEEP_ALIVE_TIME,KEEP_ALIVE_TIME_UNIT,mDecodeWorkQueue);}

Android官方开发文档Training系列课程中文版:线程执行操作之创建多线程管理器相关推荐

  1. Android官方开发文档Training系列课程中文版:目录

    原文地址 : http://android.xsoftlab.net/training/index.html 引言 在翻译了一篇安卓的官方文档之后,我觉得应该做一件事情,就是把安卓的整篇训练课程全部翻 ...

  2. Android官方开发文档Training系列课程中文版:创建自定义View之View的创建

    原文地址:http://android.xsoftlab.net/training/custom-views/index.html 引言 Android框架含有大量的View类,这些类用来显示各式各样 ...

  3. Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制

    原文地址:http://android.xsoftlab.net/training/graphics/opengl/draw.html 如果你还不清楚如何定义图形及坐标系统,请移步:Android官方 ...

  4. Android官方开发文档Training系列课程中文版:使用Fragment构建动态UI之Fragment创建

    原文地址:http://android.xsoftlab.net/training/basics/fragments/index.html 导言 为了在Android中创建动态的多面板用户界面,你需要 ...

  5. Android官方开发文档Training系列课程中文版:高效显示位图之管理位图内存

    原文地址:http://developer.android.com/training/displaying-bitmaps/manage-memory.html 除了在上一节中描述的步骤之外,还有一些 ...

  6. Android官方开发文档Training系列课程中文版:如何避免ANR?

    原文地址:http://android.xsoftlab.net/training/articles/perf-anr.html#anr 尽管你写代码可能通过了世界上所有的性能测试,但是它还是可能会让 ...

  7. Android官方开发文档Training系列课程中文版:线程执行操作之线程间通讯

    原文地址:http://android.xsoftlab.net/training/multiple-threads/communicate-ui.html 上节课我们学习了如何启动一项由Thread ...

  8. Android官方开发文档Training系列课程中文版:布局性能优化之ListView的优化

    原文地址:http://android.xsoftlab.net/training/improving-layouts/smooth-scrolling.html 想要让ListView滑动流畅的关键 ...

  9. Android官方开发文档Training系列课程中文版:数据存储之数据库存储

    原文地址:http://android.xsoftlab.net/training/basics/data-storage/databases.html 对于保存重复的结构化的数据最理想的方式就是存到 ...

最新文章

  1. 14春计算机基础作业2,北语14春《计算机基础》作业2 答案.docx
  2. SDP 协议分析 http://www.cnblogs.com/qingquan/archive/2011/08/02/2125585.html
  3. 没有精准定位,万物还能实现互联吗?
  4. Java:包的使用Pack
  5. 转载《全国研究生考试专业课资料大全(部分资料)》
  6. 配置Struts2.0
  7. c++ 共享内存_关于Linux共享内存的实验 [二] - 原因
  8. 现代制造工程——考试复习01
  9. Leetcode之跳跃游戏Ⅱ
  10. 网络教育源码 java在线教育源码
  11. Axure RP 9 for mac 高保真原型图 - 案例18 【导航栏-展开、收起】导入元件库
  12. HackerRank难题记录
  13. 用国产编程语言CBrother做微信公众号后台开发太简单
  14. biopython安装_python下如何安装biopython
  15. 3.对于python的一个非正式导言 编译之三
  16. 小学语文三年级阅读理解专项练习附答案~水上飞机
  17. python中计算梯度值
  18. nginx中配置location的root(alias)访问同一个地址文件
  19. 法拉帝港股上市:市值76亿港元 9个月交付179艘游艇
  20. 开源在线客服系统源码(PHP开发的网页在线客服聊天系统源码)

热门文章

  1. 2个字符串相等 swift_Swift快速入门(一)之 Swift基础语法
  2. 比较两个表格的不同_两表数据的核对,WPS表格似乎更加方便容易
  3. 【Pytorch神经网络理论篇】 30 图片分类模型:Inception模型
  4. teamviewer无法建立连接原因未知_3389远程无法连接的5种原因分析
  5. RIP协议及距离向量算法(详解)
  6. python 接口 、继承、重载运算符
  7. 天池在线编程 2020国庆八天乐 - 4. 生成更大的陆地(BFS)
  8. LeetCode MySQL 1158. 市场分析 I
  9. LeetCode MySQL 608. 树节点
  10. [Hands On ML] 6. 决策树