Android线程管理之ThreadPoolExecutor自定义线程池
前言:
上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己来自定义一个线程池,今天来学习一下ThreadPoolExecutor,然后结合使用场景定义一个按照线程优先级来执行的任务的线程池。
线程管理相关文章地址:
- Android线程管理之Thread使用总结
- Android线程管理之ExecutorService线程池
- Android线程管理之ThreadPoolExecutor自定义线程池
- Android线程管理之AsyncTask异步任务
- Android线程管理之ThreadLocal理解及应用场景
ThreadPoolExecutor
ThreadPoolExecutor线程池用于管理线程任务队列、若干个线程。
1.)ThreadPoolExecutor构造函数
ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue)
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler)
ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler)
ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory, RejectedExecutionHandler handler)
corePoolSize: 线程池维护线程的最少数量
maximumPoolSize:线程池维护线程的最大数量
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 线程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
threadFactory:线程池用于创建线程
handler: 线程池对拒绝任务的处理策略
2.)创建新线程
默认使用Executors.defaultThreadFactory(),也可以通过如下方式
/**
* 创建线程工厂
*/
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1); @Override
public Thread newThread(Runnable runnable) {
return new Thread(runnable, "download#" + mCount.getAndIncrement());
}
};
3.)线程创建规则
ThreadPoolExecutor对象初始化时,不创建任何执行线程,当有新任务进来时,才会创建执行线程。构造ThreadPoolExecutor对象时,需要配置该对象的核心线程池大小和最大线程池大小
1. 当目前执行线程的总数小于核心线程大小时,所有新加入的任务,都在新线程中处理。
2. 当目前执行线程的总数大于或等于核心线程时,所有新加入的任务,都放入任务缓存队列中。
3. 当目前执行线程的总数大于或等于核心线程,并且缓存队列已满,同时此时线程总数小于线程池的最大大小,那么创建新线程,加入线程池中,协助处理新的任务。
4. 当所有线程都在执行,线程池大小已经达到上限,并且缓存队列已满时,就rejectHandler拒绝新的任务。
4.)默认的RejectExecutionHandler拒绝执行策略
1. AbortPolicy 直接丢弃新任务,并抛出RejectedExecutionException通知调用者,任务被丢弃
2. CallerRunsPolicy 用调用者的线程,执行新的任务,如果任务执行是有严格次序的,请不要使用此policy
3. DiscardPolicy 静默丢弃任务,不通知调用者,在处理网络报文时,可以使用此任务,静默丢弃没有几乎处理的报文
4. DiscardOldestPolicy 丢弃最旧的任务,处理网络报文时,可以使用此任务,因为报文处理是有时效的,超过时效的,都必须丢弃
我们也可以写一些自己的RejectedExecutionHandler,例如拒绝时,直接将线程加入缓存队列,并阻塞调用者,或根据任务的时间戳,丢弃超过限制的任务。
5.)任务队列BlockingQueue
排队原则
1. 如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。
2. 如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
3. 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。
常见几种BlockingQueue实现
1. ArrayBlockingQueue : 有界的数组队列
2. LinkedBlockingQueue : 可支持有界/无界的队列,使用链表实现
3. PriorityBlockingQueue : 优先队列,可以针对任务排序
4. SynchronousQueue : 队列长度为1的队列,和Array有点区别就是:client thread提交到block queue会是一个阻塞过程,直到有一个worker thread连接上来poll task。
6.)线程池执行
execute()方法中,调用了三个私有方法
addIfUnderCorePoolSize():在线程池大小小于核心线程池大小的情况下,扩展线程池
addIfUnderMaximumPoolSize():在线程池大小小于线程池大小上限的情况下,扩展线程池
ensureQueuedTaskHandled():保证在线程池关闭的情况下,新加入队列的线程也能正确处理
7.)线程池关闭
shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
ThreadPoolExecutor实现优先级线程池
1.)定义线程优先级枚举
/**
* 线程优先级
*/
public enum Priority {
HIGH, NORMAL, LOW
}
2.)定义线程任务
/**
* 带有优先级的Runnable类型
*/
/*package*/ class PriorityRunnable implements Runnable { public final Priority priority;//任务优先级
private final Runnable runnable;//任务真正执行者
/*package*/ long SEQ;//任务唯一标示 public PriorityRunnable(Priority priority, Runnable runnable) {
this.priority = priority == null ? Priority.NORMAL : priority;
this.runnable = runnable;
} @Override
public final void run() {
this.runnable.run();
}
}
3.)定义一个PriorityExecutor继承ThreadPoolExecutor
public class PriorityExecutor extends ThreadPoolExecutor {
private static final int CORE_POOL_SIZE = 5;//核心线程池大小
private static final int MAXIMUM_POOL_SIZE = 256;//最大线程池队列大小
private static final int KEEP_ALIVE = 1;//保持存活时间,当线程数大于corePoolSize的空闲线程能保持的最大时间。
private static final AtomicLong SEQ_SEED = new AtomicLong(0);//主要获取添加任务
/**
* 创建线程工厂
*/
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
@Override
public Thread newThread(Runnable runnable) {
return new Thread(runnable, "download#" + mCount.getAndIncrement());
}
};
/**
* 线程队列方式 先进先出
*/
private static final Comparator<Runnable> FIFO = new Comparator<Runnable>() {
@Override
public int compare(Runnable lhs, Runnable rhs) {
if (lhs instanceof PriorityRunnable && rhs instanceof PriorityRunnable) {
PriorityRunnable lpr = ((PriorityRunnable) lhs);
PriorityRunnable rpr = ((PriorityRunnable) rhs);
int result = lpr.priority.ordinal() - rpr.priority.ordinal();
return result == 0 ? (int) (lpr.SEQ - rpr.SEQ) : result;
} else {
return 0;
}
}
};
/**
* 线程队列方式 后进先出
*/
private static final Comparator<Runnable> LIFO = new Comparator<Runnable>() {
@Override
public int compare(Runnable lhs, Runnable rhs) {
if (lhs instanceof PriorityRunnable && rhs instanceof PriorityRunnable) {
PriorityRunnable lpr = ((PriorityRunnable) lhs);
PriorityRunnable rpr = ((PriorityRunnable) rhs);
int result = lpr.priority.ordinal() - rpr.priority.ordinal();
return result == 0 ? (int) (rpr.SEQ - lpr.SEQ) : result;
} else {
return 0;
}
}
};
/**
* 默认工作线程数5
*
* @param fifo 优先级相同时, 等待队列的是否优先执行先加入的任务.
*/
public PriorityExecutor(boolean fifo) {
this(CORE_POOL_SIZE, fifo);
}
/**
* @param poolSize 工作线程数
* @param fifo 优先级相同时, 等待队列的是否优先执行先加入的任务.
*/
public PriorityExecutor(int poolSize, boolean fifo) {
this(poolSize, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>(MAXIMUM_POOL_SIZE, fifo ? FIFO : LIFO), sThreadFactory);
}
public PriorityExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
}
/**
* 判断当前线程池是否繁忙
* @return
*/
public boolean isBusy() {
return getActiveCount() >= getCorePoolSize();
}
/**
* 提交任务
* @param runnable
*/
@Override
public void execute(Runnable runnable) {
if (runnable instanceof PriorityRunnable) {
((PriorityRunnable) runnable).SEQ = SEQ_SEED.getAndIncrement();
}
super.execute(runnable);
}
}
里面定义了两种线程队列模式: FIFO(先进先出) LIFO(后进先出) 优先级相同的按照提交先后排序
4.)测试程序
ExecutorService executorService = new PriorityExecutor(5, false);
for (int i = 0; i < 20; i++) {
PriorityRunnable priorityRunnable = new PriorityRunnable(Priority.NORMAL, new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName()+"优先级正常");
}
});
if (i % 3 == 1) {
priorityRunnable = new PriorityRunnable(Priority.HIGH, new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName()+"优先级高");
}
});
} else if (i % 5 == 0) {
priorityRunnable = new PriorityRunnable(Priority.LOW, new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName()+"优先级低");
}
});
}
executorService.execute(priorityRunnable);
}
运行结果:不难发现优先级高基本上优先执行了 最后执行的基本上优先级比较低

Android线程管理之ThreadPoolExecutor自定义线程池的更多相关文章
- Android线程管理(一)——线程通信
线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...
- ThreadPoolExecutor自定义线程池
1.ThreadPoolExecutor创建线程池的构造函数 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long ...
- python---基础知识回顾(十)进程和线程(py2中自定义线程池和py3中的线程池使用)
一:自定义线程池的实现 前戏: 在进行自定义线程池前,先了解下Queue队列 队列中可以存放基础数据类型,也可以存放类,对象等特殊数据类型 from queue import Queue class ...
- ACE线程管理机制-面向对象的线程类ACE_Task
转载于:http://www.cnblogs.com/TianFang/archive/2006/12/05/583231.html 我们在前一章中使用ACE_Thread包装时,你一定已经注意到了一 ...
- Android线程管理之ExecutorService线程池
前言: 上篇学习了线程Thread的使用,今天来学习一下线程池ExecutorService. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Execu ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- Android线程管理之Thread使用总结
前言 最近在一直准备总结一下Android上的线程管理,今天先来总结一下Thread使用. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Executo ...
- Android线程管理之AsyncTask异步任务
前言: 前面几篇文章主要学习了线程以及线程池的创建与使用,今天来学习一下AsyncTask异步任务,学习下AsyncTask到底解决了什么问题?然而它有什么弊端?正所谓知己知彼百战百胜嘛! 线程管理相 ...
- 基于ThreadPoolExecutor,自定义线程池简单实现
一.线程池作用 在上一篇随笔中有提到多线程具有同一时刻处理多个任务的特点,即并行工作,因此多线程的用途非常广泛,特别在性能优化上显得尤为重要.然而,多线程处理消耗的时间包括创建线程时间T1.工作时间T ...
随机推荐
- 纯CSS3实现的一些酷炫效果
之前在网上看到一些用纯CSS3实现的酷炫效果,以为实现起来比较困难,于是想看看具体是怎么实现的. 一.笑脸猫动画 实现效果如下: 这个实现起来确实比较麻烦,很多地方需要花时间,有耐心地调整. 1.先看 ...
- git-简单流程(学习笔记)
这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...
- css-父标签中的子标签默认位置
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- javascript中的事件冒泡和事件捕获
1.事件冒泡 IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档).以下面的HTML ...
- ASP.NET加密和解密数据库连接字符串
大家知道,在应用程序中进行数据库操作需要连接字符串,而如果没有连接字符串,我们就无法在应用程序中完成检索数据,创建数据等一系列的数据库操作.当有人想要获取你程序中的数据库信息,他首先看到的可能会是We ...
- 深入Java虚拟机--判断对象存活状态
程序计数器,虚拟机栈和本地方法栈 首先我们先来看下垃圾回收中不会管理到的内存区域,在Java虚拟机的运行时数据区我们可以看到,程序计数器,虚拟机栈,本地方法栈这三个地方是比较特别的.这个三个部分的特点 ...
- 负载均衡——nginx理论
nginx是什么? nginx是一个强大的web服务器软件,用于处理高并发的http请求和作为反向代理服务器做负载均衡.具有高性能.轻量级.内存消耗少,强大的负载均衡能力等优势. nginx架构? ...
- Android 微信第三方登录(个人笔记)
今天在写微信登录,花了半天时间搞定.然后写下自己的笔记,希望帮助更多的人...欢迎各位指教. 微信授权登录,官方说的不是很清楚.所以导致有一部分的坑. 微信注册应用平台的应用签名,下载 微信签名生成工 ...
- 项目自动化建构工具gradle 入门1——输出helloWorld
先来一个简单的例子,4个步骤: 1.进入D:\work\gradle\java 目录 ,您电脑没这目录? 那辛苦自己一级一级建立起来吧 新建文件build.gradle,文件内容是: apply p ...
- Spring Security OAuth2 开发指南
官方原文:http://projects.spring.io/spring-security-oauth/docs/oauth2.html 翻译及修改补充:Alex Liao. 转载请注明来源:htt ...