0.前言

转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52415337

使用线程池可以给我们带来很多好处,首先通过线程池中线程的重用,减少创建和销毁线程的性能开销。其次,能控制线程池中的并发数,否则会因为大量的线程争夺CPU资源造成阻塞。最后,线程池能够对线程进行管理,比如使用ScheduledThreadPool来设置延迟N秒后执行任务,并且每隔M秒循环执行一次。

下面会通过介绍线程池中的真正实现者——ThreadPoolExecutor来引出Android中的4类线程池的使用以及特性分析,会加上笔者自己的理解,和自认为比较恰当的比喻,帮助理解。

1.凡事得靠ThreadPoolExecutor(铺垫环节,懂的直接跳过)

Executor作为一个接口,它的具体实现就是ThreadPoolExecutor。

Android中的线程池都是直接或间接通过配置ThreadPoolExecutor来实现不同特性的线程池。

先介绍ThreadPoolExecutor的一个常用的构造方法。

  1. /*
  2. *@ ThreadPoolExecutor构造参数介绍
  3. *@author SEU_Calvin
  4. * @date 2016/09/03
  5. */
  6. public ThreadPoolExecutor(
  7. //核心线程数,除非allowCoreThreadTimeOut被设置为true,否则它闲着也不会死
  8. int corePoolSize,
  9. //最大线程数,活动线程数量超过它,后续任务就会排队
  10. int maximumPoolSize,
  11. //超时时长,作用于非核心线程(allowCoreThreadTimeOut被设置为true时也会同时作用于核心线程),闲置超时便被回收
  12. long keepAliveTime,
  13. //枚举类型,设置keepAliveTime的单位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等
  14. TimeUnit unit,
  15. //缓冲任务队列,线程池的execute方法会将Runnable对象存储起来
  16. BlockingQueue<Runnable> workQueue,
  17. //线程工厂接口,只有一个new Thread(Runnable r)方法,可为线程池创建新线程
  18. ThreadFactory threadFactory)

ThreadPoolExecutor的各个参数所代表的特性注释中已经写的很清楚了,那么ThreadPoolExecutor执行任务时的心路历程是什么样的呢?(以下用currentSize表示线程池中当前线程数量)

(1)当currentSize<corePoolSize时,没什么好说的,直接启动一个核心线程并执行任务。

(2)当currentSize>=corePoolSize、并且workQueue未满时,添加进来的任务会被安排到workQueue中等待执行。

(3)当workQueue已满,但是currentSize<maximumPoolSize时,会立即开启一个非核心线程来执行任务。

(4)当currentSize>=corePoolSize、workQueue已满、并且currentSize>maximumPoolSize时,调用handler默认抛出RejectExecutionExpection异常。

2. Android中的四类线程池

Android中最常见的四类具有不同特性的线程池分别为FixThreadPool、CachedThreadPool、ScheduleThreadPool以及SingleThreadExecutor。

2.1     FixThreadPool(一堆人排队上公厕)

  1. /*
  2. *@FixThreadPool介绍
  3. *@author SEU_Calvin
  4. * @date 2016/09/03
  5. */
  6. public static ExecutorService newFixThreadPool(int nThreads){
  7. return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
  8. }
  9. //使用
  10. Executors.newFixThreadPool(5).execute(r);

(1)从配置参数来看,FixThreadPool只有核心线程,并且数量固定的,也不会被回收,所有线程都活动时,因为队列没有限制大小,新任务会等待执行。

(2)【前方高能,笔者脑洞】FixThreadPool其实就像一堆人排队上公厕一样,可以无数多人排队,但是厕所位置就那么多,而且没人上时,厕所也不会被拆迁,哈哈o(∩_∩)o ,很形象吧。

(3)由于线程不会回收,FixThreadPool会更快地响应外界请求,这也很容易理解,就好像有人突然想上厕所,公厕不是现用现建的。

2.2     SingleThreadPool(公厕里只有一个坑位)

  1. /*
  2. *@SingleThreadPool介绍
  3. *@author SEU_Calvin
  4. * @date 2016/09/03
  5. */
  6. public static ExecutorService newSingleThreadPool (int nThreads){
  7. return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor (1, 1, 0, TimeUnit. MILLISECONDS, new LinkedBlockingQueue<Runnable>()) );
  8. }
  9. //使用
  10. Executors.newSingleThreadPool ().execute(r);

(1)从配置参数可以看出,SingleThreadPool只有一个核心线程,确保所有任务都在同一线程中按顺序完成。因此不需要处理线程同步的问题。

(2)【前方高能,笔者脑洞】可以把SingleThreadPool简单的理解为FixThreadPool的参数被手动设置为1的情况,即Executors.newFixThreadPool(1).execute(r)。所以SingleThreadPool可以理解为公厕里只有一个坑位,先来先上。为什么只有一个坑位呢,因为这个公厕是收费的,收费的大爷上年纪了,只能管理一个坑位,多了就管不过来了(线程同步问题)。

2.3     CachedThreadPool(一堆人去一家很大的咖啡馆喝咖啡)

  1. /*
  2. *@CachedThreadPool介绍
  3. *@author SEU_Calvin
  4. * @date 2016/09/03
  5. */
  6. public static ExecutorService newCachedThreadPool(int nThreads){
  7. return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit. SECONDS, new SynchronousQueue<Runnable>());
  8. }
  9. //使用
  10. Executors.newCachedThreadPool().execute(r);

(1)CachedThreadPool只有非核心线程,最大线程数非常大,所有线程都活动时,会为新任务创建新线程,否则利用空闲线程(60s空闲时间,过了就会被回收,所以线程池中有0个线程的可能)处理任务。

(2)任务队列SynchronousQueue相当于一个空集合,导致任何任务都会被立即执行。

(3)【前方高能,笔者脑洞】CachedThreadPool就像是一堆人去一个很大的咖啡馆喝咖啡,里面服务员也很多,随时去,随时都可以喝到咖啡。但是为了响应国家的“光盘行动”,一个人喝剩下的咖啡会被保留60秒,供新来的客人使用,哈哈哈哈哈,好恶心啊。如果你运气好,没有剩下的咖啡,你会得到一杯新咖啡。但是以前客人剩下的咖啡超过60秒,就变质了,会被服务员回收掉。

(4)比较适合执行大量的耗时较少的任务。喝咖啡人挺多的,喝的时间也不长。

2.4    ScheduledThreadPool(4个里面唯一一个有延迟执行和周期重复执行的线程池)

  1. /*
  2. *@ScheduledThreadPool介绍
  3. *@author SEU_Calvin
  4. * @date 2016/09/03
  5. */
  6. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize){
  7. return new ScheduledThreadPoolExecutor(corePoolSize);
  8. }
  9. public ScheduledThreadPoolExecutor(int corePoolSize){
  10. super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedQueue ());
  11. }
  12. //使用,延迟1秒执行,每隔2秒执行一次Runnable r
  13. Executors. newScheduledThreadPool (5).scheduleAtFixedRate(r, 1000, 2000, TimeUnit.MILLISECONDS);

(1)核心线程数固定,非核心线程(闲着没活干会被立即回收)数没有限制。

(2)从上面代码也可以看出,ScheduledThreadPool主要用于执行定时任务以及有固定周期的重复任务。

至此Android中最常见的四类不同特性的线程池内容总结完毕。

转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52415337

Android开发——Android中常见的4种线程池(保证你能看懂并理解)的更多相关文章

  1. (转载)Android开发——Android中常见的4种线程池(保证你能看懂并理解)

    0.前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52415337 使用线程池可以给我们带来很多好处,首先通过线程池中线程的重用 ...

  2. Java中常用的四种线程池

    在Java中使用线程池,可以用ThreadPoolExecutor的构造函数直接创建出线程池实例,如何使用参见之前的文章Java线程池构造参数详解.不过,在Executors类中,为我们提供了常用线程 ...

  3. Java并发编程:Java的四种线程池的使用,以及自定义线程工厂

    目录 引言 四种线程池 newCachedThreadPool:可缓存的线程池 newFixedThreadPool:定长线程池 newSingleThreadExecutor:单线程线程池 newS ...

  4. Android开发——Android多进程以及使用场景介绍

    个层级,具体可以查看Android开发--Android进程保活招式大全中1.1部分的内容,这里就不赘述了. 根据进程中当前活动组件的重要程度,Android 会将进程评定为它可能达到的最高级别.例如 ...

  5. Android开发——Android M(6.0) 权限解决方案

    Android开发--Android M(6.0) 权限解决方案 自从Android M(6.0)发布以来,权限管理相比以前有了很大的改变,很多程序员发现之前运行的好好的Android应用在Andro ...

  6. Java中常见的5种WEB服务器介绍

    这篇文章主要介绍了Java中常见的5种WEB服务器介绍,它们分别是Tomcat.Resin.JBoss.WebSphere.WebLogic,需要的朋友可以参考下 Web服务器是运行及发布Web应用的 ...

  7. Android开发-Android Studio问题以及解决记录

    [Android开发] Android Studio问题以及解决记录   http://blog.csdn.net/niubitianping/article/details/51400721 1.真 ...

  8. Vue基础01vue的基本示例,vue的双向数据绑定,vue中常见的几种用法,vue相关常见指令

    自学vue框架,每天记录重要的知识点,与大家分享!有不足之处,希望大家指正. 本篇将讲述:vue的基本示例,vue的双向数据绑定,vue中常见的几种用法,vue相关常见指令 前期学习基础,使用vue. ...

  9. ORACLE中常见的几种锁

    ORACLE中常见的几种锁: 0:none 1:null 空 2:Row-S 行共享(RS):共享表锁,sub share 3:Row-X 行独占(RX):用于行的修改,sub exclusive 4 ...

随机推荐

  1. Java基础——泛型

    一.定义 泛型(generic)是指参数化类型的能力.可以定义带泛型类型的类或方法,随后编译器会用具体的类型来替换它(泛型实例化).使用泛型的主要优点是能够在编译时,而不是在运行时检测出错误.它是jd ...

  2. 【公众号转载】MyBatis拦截器原理探究

    MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...

  3. Wooden Sticks(hdu1501)(sort,dp)

    Wooden Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  4. C 中结构体对齐

    参考 百度百科内存对齐 对齐作用 可以使得以最少的次数将操作数加载到寄存器中,如果数据没有对齐,则当CPU以最小读取数据大小从内存读入数据时可能只取到了一部分数据,而对齐情况下可以一次读入. 对齐修改 ...

  5. JavaScript弹出窗口方法

    本文实例汇总了常用的JavaScript弹出窗口方法,供大家对比参考,希望能对大家有所帮助.详细方法如下: 1.无提示刷新网页: 大家有没有发现,有些网页,刷新的时候,会弹出一个提示窗口,点“确定”才 ...

  6. Context 上下文

    全称:context 解释:上下文,在我们的开发的程序中,通常使用context上下文. 理解:结合实际生活我们可以把它理解为是语境,比如A说:我喜欢他. 那么这个他是谁,我们不知道,如果在这句话之前 ...

  7. CentOS 7 镜像下载

    新版本系统镜像下载(当前最新是CentOS 7.4版本) CentOS官网 官网地址 http://isoredirect.centos.org/centos/7.4.1708/isos/x86_64 ...

  8. h5新增加的存储方法

    h4中使用的cookie把用户信息保存在客户端浏览器,但是它受到很多限制. 大小:最多能存储4k 带宽:它是随着http请求一起发送到服务器的,因此浪费一部分的带宽. 复杂度:操作复杂. h5新增加了 ...

  9. 【代码笔记】iOS-UITableView上的button点击事件

    代码. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController < ...

  10. 【读书笔记】iOS-网络-使用Bonjour实现自组织网络

    Bonjour就是这样一种技术:设备可以通过它轻松探测并连接到相同网络中的其他设备,整个过程只需要很少的用户参与或是根本就不需要用户参与.该框架提供了众多适合于移动的使用场景,如基于网络的游戏,设备间 ...