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

摘要:
接下来,我们将通过介绍线程池的真正实现者ThreadPoolExecutor来介绍Android中四种类型线程池的使用和特性分析。将添加作者自己的理解和隐喻,以帮助理解。Android中的线程池是一个具有不同特性的线程池,可以通过配置ThreadPoolExecutor直接或间接实现。当currentSize<corePoolSize时,没有什么好说的。启动核心线程并直接执行任务。2.Android中的四个线程池Android中具有不同特征的四个最常见的线程池是FixThreadPool、CachedThreadPool、ScheduleThreadPool和SingleThreadExecutor。因此,不需要处理线程同步。

0.前言

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

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

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

 

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

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

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

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

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

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

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

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

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

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


2 Android中的四类线程池

Android中最常见的四类具有不同特性的线程池分别为FixThreadPoolCachedThreadPoolScheduleThreadPool以及SingleThreadExecutor

 

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

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

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

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

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


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

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

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

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


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

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

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

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

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

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


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

/*
*@ScheduledThreadPool介绍
*@author SEU_Calvin
* @date 2016/09/03
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize){
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize){
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedQueue ());
}
//使用,延迟1秒执行,每隔2秒执行一次Runnable r
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种线程池(保证你能看懂并理解)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇spring boot 实现多个 interceptor 并指定顺序《TCP原理》下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android JNI开发高级篇有关Android JNI开发中比较强大和有用的功能就是从JNI层创建、构造Java的类或执行Java层的方法获取属性等操作。 一、类的相关操作 1. jclass FindClass(JNIEnv *env, const char *name);

有关Android JNI开发中比较强大和有用的功能就是从JNI层创建、构造Java的类或执行Java层的方法获取属性等操作。 一、类的相关操作 1.jclass FindClass(JNIEnv *env, const char *name);查找类 该函数可能做过Java开发的不会陌生,这个是JNI层的实现,需要注意的是第二个参数为const char...

【原创】从4个9到5个9可用性调优-总章

适用场景&适读对象场景关键词:互联网 分布式 业务集群 qps高 扛量 高可用 涉及内容:缓存调优 GC调优 隔离 上下游防护 运维优化 适读对象:资深业务开发同学,团队leader Part1.背景 之前年底线上用户端工程出了一次可用性故障,导致用户进app首页白屏,系统不可用。 具体原因是:【redis单点大热key叠加pipeline导致...

如何用Android Studio同时使用SVN和Git管理项目

本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 这篇来讲讲如何在 Android Studio 上同时用 SVN 和 Git 来管理项目。我知道,你肯定会说我吃饱了撑着,没事找事做,为啥要同时用 SVN 和 Git 来管理项目。问题是,我也不想啊,我也很无奈啊(:(哭丧脸)。 为啥要同时用 SVN 和 Git 管理项目 这小题目也可以叫...

解决Android与服务器交互大容量数据问题

对于目前的状况来说,移动终端的网络状况没有PC网络状况那么理想。在一个Android应用中,如果需要接收来自服务器的大容量数据,那么就不得不考虑客户的流量问题。本文根据笔者的一个项目实战经验出发,解决大容量数据的交互问题,解决数据大小会根据实际情况动态切换问题(服务器动态选择是否要压缩数据,客户端动态解析数据是否是被压缩的),还有数据交互的编码问题。 解决...

html5 如何打包成apk,将H5封装成android应用APK文件的几种方法

直接使用编程软件提供的方法: 1、需要下载安装MyEclipse2014,Android SDK,eclipse(需配置Android开发环境) Java和Android环境安装与配置。 2、打开MyEclipse2014,新建一个HTML5 Mobile Application Project,命名,例如:hello。 3、html5程序在工程www目...

解决某些Android Permission denied

最近遇到一个问题,总是在模拟器重报Permission denied错误,于是我直接在手机上测试,发现没有错误,于是很郁闷,反复在AndroidManifest中加入权限 <uses-permission android:name="android.permission.INTERNET"/> <uses-permission andr...