个人博客:

http://www.milovetingting.cn

在Android中,主线程不能执行耗时的操作,否则可能会导致ANR。那么,耗时操作应该在其它线程中执行。线程的创建和销毁都会有性能开销,创建过多的线程也会由于互相抢占系统资源而导致阻塞的现象。这个时候,就需要使用线程池。

线程池的优点可以概括为以下几点:

  • 1、重用线程池中的线程,避免线程创建、销毁带来的性能开销;

  • 2、能有效地控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源导致的阻塞现象;

  • 3、能够对线程进行简单的管理。

以上线程池的优点引用自《Android开发艺术探索》

线程池的具体实现类为ThreadPoolExecutor,ThreadPoolExecutor继承自AbstractExecutorService,AbstractExecutorService又实现了ExecutorService接口,ExecutorService继承自Executor。

ThreadPoolExecutor有四个重载的构造方法:

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
} public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
} public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
} public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}

最终都调用到了:

/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}

对应这个方法中的参数:

  • corePoolSize:核心线程数。如果没有设置allowCoreThreadTimeOut为true,则核心线程空闲时也不会销毁。如果设置allowCoreThreadTimeOut为true,则受keepAliveTime控制,空闲时间超过keepAliveTime,会被回收。

  • maximumPoolSize:最大线程数。

  • keepAliveTime:非核心线程的空闲超时时长。超过这个时间,非核心线程会被回收。核心线程如果allowCoreThreadTimeOut为true,则在空闲超过这个时间也会被回收。

  • unit:超时的单位。

  • workQueue:线程池中的任务队列。通过线程池的execute()方法提交的Runnable任务会被放入任务队列中。

  • threadFactory:线程工厂。

  • handler:饱和策略。当任务队列和线程池都满后,对新提交的任务的处理策略。

ThreadPoolExecutor执行任务的规则:

  • 1、如果线程池中的线程数量未达到核心线程数量,则开启一个新的核心线程来执行任务

  • 2、如果线程池中的线程数量已经大于等于核心线程数量,则会把新的任务放入任务队列中

  • 3、如果任务队列已满,并且线程池中的线程未满,则开启非核心线程来处理新的任务

  • 4、如果任务队列和线程池都已满,则会交给handler饱和策略来处理

下面通过一个简单的案例来验证以上规则:

static class WorkThread implements Runnable {

	private String name;

	public WorkThread(String name) {
this.name = name;
} public void run() {
try {
Thread.sleep(5000);
System.out.println("Thread: " + name + " work finish");
} catch (Exception e) {
e.printStackTrace();
} }
}; Executor executor = new ThreadPoolExecutor(5, 100, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));
for (int i = 0; i < 20; i++) {
WorkThread thread = new WorkThread("" + i);
executor.execute(thread);
}

定义了一个线程池,核心线程池数量为5,线程数量为100,超时时间为60秒,任务队列为5。在子线程中,sleep 5秒来模拟耗时的操作。然后开启了20个线程,并放入线程池中执行。执行的结果如下:

Thread: 0 work finish
Thread: 1 work finish
Thread: 13 work finish
Thread: 10 work finish
Thread: 3 work finish
Thread: 11 work finish
Thread: 4 work finish
Thread: 2 work finish
Thread: 19 work finish
Thread: 18 work finish
Thread: 17 work finish
Thread: 15 work finish
Thread: 16 work finish
Thread: 14 work finish
Thread: 12 work finish
Thread: 5 work finish
Thread: 9 work finish
Thread: 8 work finish
Thread: 7 work finish
Thread: 6 work finish

前五个线程在核心线程中执行,第6-10个线程由于核心线程已满,因此在任务队列中等待执行,第11-20个线程,由于核心线程和队列都已满,而线程池中还可以开启线程,因此在非核心线程中执行。从结果来看,线程0-4,10-19会先执行完,然后任务队列中的线程5-9才执行,验证了以上的线程池任务执行规则。

为便于使用线程池,线程池还有几种简便的定义方法:

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
} public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
} public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
} public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
} public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}

通过Executors的static方法来创建。其中:

  • FixedThreadPool:线程数量固定的线程池。从方法的定义来看,这种线程池里的线程全都是核心线程,并且没有超时时间,任务队列也是没有限制的。

  • CachedThreadPool:这种线程池没有核心线程,全是非核心线程,并且超时时间为60秒,任务队列没有限制。这种线程适合执行大量的耗时较短的任务。

  • SingleThreadExecutor:只有一个核心线程,没有超时时间,任务队列没有限制。可以确保任务按顺序执行。

  • ScheduledThreadPool:核心线程数量固定。非核心线程没有限制。非核心线程闲置时会被立即回收。这类线程池适合执行定时任务和具有固定周期的重复任务。

Android中的线程池的更多相关文章

  1. android中的线程池学习笔记

    阅读书籍: Android开发艺术探索 Android开发进阶从小工到专家 对线程池原理的简单理解: 创建多个线程并且进行管理,提交的任务会被线程池指派给其中的线程进行执行,通过线程池的统一调度和管理 ...

  2. android中对线程池的理解与使用

    前段时间有幸接到腾讯上海分公司的 Android开发面试,虽然最后一轮被毙了.但还是得总结一下自己在android开发中的一些盲点,最让我尴尬的是面试官问我几个android中线程池的使用与理解..哎 ...

  3. Android中的线程池概述

    线程池 Android里面,耗时的网络操作,都会开子线程,在程序里面直接开过多的线程会消耗过多的资源,在众多的开源框架中也总能看到线程池的踪影,所以线程池是必须要会把握的一个知识点; 线程运行机制 开 ...

  4. Android中的线程池 ThreadPoolExecutor

    线程池的优点: 重用线程池中的线程,避免因为线程的创建和销毁带来的性能消耗 能有效的控制线程的最大并发数,避免大量的线程之间因抢占系统资源而导致的阻塞现象 能够对线程进行简单的管理,并提供定时执行以及 ...

  5. android开发学习 ------- 【转】 android中的线程池

    线程很常见 , https://blog.csdn.net/seu_calvin/article/details/52415337    参考,保证能看懂.

  6. Android开发之线程池使用总结

    线程池算是Android开发中非常常用的一个东西了,只要涉及到线程的地方,大多数情况下都会涉及到线程池.Android开发中线程池的使用和Java中线程池的使用基本一致.那么今天我想来总结一下Andr ...

  7. Android中后台线程如何与UI线程交互

    我想关于这个话题已经有很多前辈讨论过了.今天算是一次学习总结吧. 在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须 ...

  8. java 中的线程池

    1.实现下面的一个需求,控制一个执行函数只能被五个线程访问 package www.weiyuan.test; public class Test { public static void main( ...

  9. Java5中的线程池实例讲解

    Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活.本文通过一个网络服务器模型,来实践Java5的多线程 ...

随机推荐

  1. 别开心太早,Python 官方文档的翻译差远了

    近几天,很多公众号发布了 Python 官方文档的消息.然而,一个特别奇怪的现象就发生了,让人啼笑皆非. Python 文档的中文翻译工作一直是“默默无闻”,几个月前,我还吐槽过这件事<再聊聊P ...

  2. 游戏AI之初步介绍(0)

    目录 游戏AI是什么? 游戏AI和理论AI 智能的假象 (更新)游戏AI和机器学习 介绍一些游戏AI 4X游戏AI <求生之路>系列 角色扮演/沙盒游戏中的NPC 游戏AI 需要学些什么? ...

  3. Unity 用ml-agents机器学习造个游戏AI吧(1)(Windows环境配置)

    前言:以前觉得机器学习要应用于游戏AI,还远得很. 最近看到一些资料后,突发兴致试着玩了玩Unity机器学习,才发觉机器学习占领游戏AI的可能性和趋势. Unity训练可爱柯基犬Puppo 机器学习训 ...

  4. traefik 结合 docker-compose 的快速安装及使用

    traefik 介绍 traefik 是一个为了让部署微服务更加便捷而诞生的现代HTTP反向代理.负载均衡工具. 它支持多种后台 (Docker, Swarm, Kubernetes, Maratho ...

  5. Java基础练习4(内存管理)

    请根据如下程序代码,画出对应的内存管理图(不需要画方法区),并写出输出结果. 1. public class Cell{ int row; int col; public Cell(int row,i ...

  6. AI应用开发实战 - 从零开始搭建macOS开发环境

    AI应用开发实战 - 从零开始搭建macOS开发环境 本视频配套的视频教程请访问:https://www.bilibili.com/video/av24368929/ 建议和反馈,请发送到 https ...

  7. 【工具篇】Sublime Text 2 安装汉化破解、插件包安装教程详解

    Sublime Text概述: Sublime Text是一个代码编辑器,也是HTML和散文先进的文本编辑器. 漂亮的用户界面和非凡的功能,例如:迷你地图,多选择,Python插件,代码段等等. 完全 ...

  8. PMBook - 6.项目进度管理

      6.3 排列活动顺序 6.3.1 排列活动顺序:输入 6.3.1.1 项目管理计划 6.3.1.2 项目文件 6.3.1.3 事业环境因素 6.3.1.4 组织过程资产 6.3.2 排列活动顺序: ...

  9. perl学习笔记--搭建开发环境

    windows下perl开发环境搭建 perl下载地址:http://www.activestate.com/developer-tools 各个插件的安装方法:(通过代理上网的方法) 方法一:pad ...

  10. MAC系统上安装Apache ab测试工具

    第一步:下载 Apache HTTP Server http://httpd.apache.org/download.cgi#apache24 第二步:安装brew工具 https://brew.sh ...