引言

Android的线程池概念来自于Java的Executor,真正的线程池实现为ThreadPoolExecutor。在Android中,提供了4类不同的线程池,具体下面会说到。为什么使用线程池呢?而不是使用Thread创建线程呢?因为使用线程池有以下几个优点:

  • 重用线程池的线程,避免因为线程的创建和销毁所带来的性能开销
  • 能有效控制线程池的最大并发数,避免线程之间抢占资源导致阻塞
  • 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能

所以需要多次创建Thread时使用线程池较好。

ThreadPoolExecutor

它是线程池的真正实现,构造函数提供一系列的参数配置线程池。

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
  • corePoolSize:核心线程数,默认情况下,即时处于闲置状态下,核心线程会在线程一直存活;如果设置allowCoreThreadTimeOut为true,闲置的核心线程等待任务期间会有超时策略,时间间隔由keepAliveTime设置,最大为CPU核心数+1
  • maximumPoolSize:线程池容纳最大线程数,当活动线程数超过这个数值,后续的新任务会导致阻塞,最大为CPU核心数2倍+1
  • keepAliveTime:非核心线程闲置时超时的时长,如果设置allowCoreThreadTimeOut为true,即作用于闲置的核心线程
  • unit:时间单位,使用TimeUnit枚举
  • workQueue:线程池中的任务队列,通过线程池execute方法提交Runnable对象会存储这个参数中,容量为128
  • threadFactory:线程工厂,为线程池提供创建新线程的功能
  • handler:线程池对拒绝任务的处理策略。一般是队列已满或者无法成功执行任务,这时ThreadPoolExecutor会调用handler的rejectedExecution方法来通知调用者,有四个策略:
    • ThreadPoolExecutor.AbortPolicy() 直接抛出异常RejectedExecutionException
    • ThreadPoolExecutor.CallerRunsPolicy() 直接调用run方法并且阻塞执行
    • ThreadPoolExecutor.DiscardPolicy() 直接丢弃后来的任务
    • ThreadPoolExecutor.DiscardOldestPolicy() 丢弃在队列中队首的任务

执行任务规则可用currentSize表示线程池中当前线程数量,将上述过程可以表示如下

  • 当currentSize < corePoolSize时,直接启动一个核心线程并执行任务
  • 当currentSize>=corePoolSize、并且workQueue未满时,添加进来的任务会被安排到workQueue中等待执行
  • 当workQueue已满,但是currentSize<maximumPoolSize时,会立即开启一个非核心线程来执行任务
  • 当currentSize>=corePoolSize、workQueue已满、并且currentSize>maximumPoolSize时,调用handler默认抛出RejectExecutionExpection异常
  • 当currentSize >corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
  • 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

FixedThreadPool

通过Executors的newFixedThreadPool方法创建,它是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭了。当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。由于FixedThreadPool只有核心线程并且这些核心线程不会被回收,这意味着它能够更加快速地响应外界的请求。

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

CachedThreadPool

通过Executors的newCachedThreadPool方法创建,它是一种线程数量不定的线程池,它只有非核心线程,并且最大线程数为Integer.MAX_VALUE,从CachedThreadPool的特性来看,这类线程池比较适合执行大量的耗时较少的任务,当整个线程池都处于闲置状态时,线程池中的线程都会超时而被停止,这个时候CachedThreadPool之中实际上是没有任何线程的,它几乎是不占用任何系统资源的。

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

ScheduledThreadPool

通过Executors的newScheduledThreadPool方法创建,它的核心线程是固定的,非核心线程数是没有限制的,主要用于执行定时任务和具有固定周期的重复任务。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}

SingleThreadExecutor

通过Executors的newSingleThreadExecutor方法创建,它只有一个核心线程,确保所有任务都在同一个线程中按顺序执行,使得这些不需要处理线程同步问题。

public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

最新文章

  1. MVC自动绑定整数数组
  2. socket:通常每个套接字地址(协议/网络地址/端口)只允许使用一次
  3. Hadoop入门系列一
  4. super语句
  5. subprocess实现管道
  6. Windows和Windows Phone应用终于可以使用FFmpeg了
  7. NGINX + LUA实现复杂的控制 --源自http://outofmemory.cn/code-snippet/14396/nginx-and-lua
  8. Python学习笔记:魔术方法详解
  9. event driven的一些概念
  10. js选中当前菜单后高亮显示的导航条
  11. Windows和Linux下Mysql 重置root 密码
  12. vs2015无法解析外部符号__imp__fprintf
  13. python sys.exit()函数说明
  14. Extjs Store 的用法详解
  15. Cocos2d-x 精灵碰撞检測(方法二)
  16. boost库之geometry
  17. JQuery动画animate的stop方法使用详解
  18. Tomcat--安装与部署(一)
  19. dict的操作和三级菜单
  20. LeetCode算法题-Longest Continuous Increasing Subsequence(Java实现)

热门文章

  1. Unity Animator动画状态机 深入理解(三)二维混合树
  2. Leetcode 347. Top K Frequent Elements
  3. VBA的打开关闭保存另存为等事件无法正常跑的原因
  4. sql语句中left join、inner join中的on与where的区别
  5. DOM操作(Window.document对象)
  6. Python字典 (dictionary)
  7. cdoj 1136 邱老师玩游戏 树形背包
  8. Lucene基础(二)--索引的操作
  9. 谁能告诉我为什么sum_area输出总是0(多边形重心问题)
  10. Bee Framework_百度百科
  11. 王佩丰第一讲 认识excel笔记
  12. http://codeforces.com/contest/536/problem/B
  13. `TypeError: torch.mm received an invalid combination of arguments - got (torch.FloatTensor, Variable),
  14. [Oracle]如何在Oracle中设置Event
  15. win10图片打开方式里没有默认照片查看器的解决方法
  16. [机翻] WIRER ON THE WIRE - SIGNALR协议的非正式描述
  17. 5.4 使用 Razor 表达式
  18. MySQL学习【第二篇安装】
  19. java基础79 会话管理(Cookie技术、Session技术)
  20. 配置tomcat全局c3p0连接池