Android中的线程池

很久没有更新了,首先跟各位说声对不起。近段时间陷进了失眠的深渊难以自拔,工作、生活一团糟,每天都是满满的负能量,学习上并没有什么心得值得分享,所以也就无从下笔。几经挣扎,感觉好点了。今日见到项目中前辈封装了一个线程池的管理类,其实非常简单,寥寥数十行代码。

public class ThreadPoolManager {
private ExecutorService service;  
 private static ThreadPoolManager manager;  
 private ThreadPoolManager() {
  int num = Runtime.getRuntime().availableProcessors();       
  this.service = Executors.newFixedThreadPool(num * 2);  
 }
public static ThreadPoolManager getInstance() {
if(manager == null) {
manager = new ThreadPoolManager();      
 }
return manager;  
 }
public void addTask(Runnable runnable) {
this.service.submit(runnable);   }}

使用很简单,通过单例获得管理类的实例,调用addTask方法,传入一个Runnable对象即可进行异步的操作。
在以往的项目中,大部分的耗时操作都是网络操作,譬如接口请求,文件下载等等,这些一般都是使用第三方封装好的网络框架,遇到一些IO类的耗时操作一般都是直接通过继承Thread类或者实现Runnable接口或者AsyncTask(其实AsyncTask中也使用了线程池)去实现。虽然一直知道有个叫线程池的东西,却一直没有去使用,因为之前了解不多,不如Thread、Runnable和AsyncTask用得顺手,直到我见到这个线程池管理类,我才认真去了解了一下。总的来说,用线程池有以下3个优点:
1.重用已经创建的好的线程,避免频繁创建进而导致的频繁GC
2.控制线程并发数,合理使用系统资源,提高应用性能
3.可以有效的控制线程的执行,比如定时执行,取消执行等
Android中的线程池的概念来源于Jaca中的Executor接口,它的真正实现类为ThreadPoolExecutor。ThreadPoolExecutor中提供了一系列参数来配置线程池,通过不同的参数可以创建不同的线程池,从线程池的功能特性来说,Android的线程池主要分为四类,这四类线程池可以通过Executor所提供的工厂方法来得到。由于Android中的线程池都是直接或间接通过配置ThreadPoolExecutor来实现的,所以先介绍一下ThreadPoolExecutor。
下面这个是ThreadPoolExecutor的常用构造方法

public ThreadPoolExecutor(int corePoolSize,    
 int maximumPoolSize,   
  long keepAliveTime,   
 TimeUnit unit,    
 BlockingQueue<Runnable> workQueue,     
ThreadFactory threadFactory,    
 RejectedExecutionHandler handler)

corePoolSize 线程池中核心线程的数量
maximumPoolSize 线程池中最大线程数量
keepAliveTime 非核心线程的超时时长,当系统中非核心线程闲置时间超过keepAliveTime之后,则会被回收。如果ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,则该参数也表示核心线程的超时时长
unit 第三个参数的单位,有纳秒、微秒、毫秒、秒、分、时、天等
workQueue 线程池中的任务队列,该队列主要用来存储已经被提交但是尚未执行的任务。存储在这里的任务是由ThreadPoolExecutor的execute方法提交来的。
threadFactory 为线程池提供创建新线程的功能,这个我们一般使用默认即可
handler 拒绝策略,当线程无法执行新任务时(一般是由于线程池中的线程数量已经达到最大数或者线程池关闭导致的),默认情况下,当线程池无法处理新线程时,会抛出一个RejectedExecutionException。
ThreadPoolExecutor遵循如下规则:1.execute一个线程之后,如果线程池中的线程数未达到核心线程数,则会立马启用一个核心线程去执行
2.execute一个线程之后,如果线程池中的线程数已经达到核心线程数,且workQueue未满,则将新线程放入workQueue中等待执行
3.execute一个线程之后,如果线程池中的线程数已经达到核心线程数但未超过非核心线程数,且workQueue已满,则开启一个非核心线程来执行任务
4.execute一个线程之后,如果线程池中的线程数已经超过非核心线程数,则拒绝执行该任务
以下是的简单使用方法

ThreadPoolExecutor mThreadPoolExecutor new ThreadPoolExecutor(3, 5,1,
 TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(128));
mThreadPoolExecutor.execute(new Runnable() {
@Override  
public void run() {
//耗时操作  
}});

下面来介绍Android中常见的四类具有不同功能特性的线程池,它们都直接或间接地通过配置ThreadPoolExecutor来实现自己的功能特性,这四类线程池分别是FixThreadPool、CachedThreadPool、ScheduleThreadPool以及SingleThreadExecutor。
1、FixThreadPool

//构造方法
public static ExecutorService newFixThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads, nThreads, 0L,TimeUnit.MILLISECONDS, 
new LinkedBlockingQueue<Runnable>());
}
//使用  
Executors.newFixThreadPool(5).execute(r);

它是一种线程数量固定的线程池,当线程处于空闲状态时并不会被回收除非线程池被关闭了。当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。由于FixThreadPool只有核心线程并且这些线程不会被回收,意味着它的响应会更加迅速。
2、CachedThreadPool

public static ExecutorService newCachedThreadPool(int nThreads){
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, 
TimeUnit. SECONDS, new SynchronousQueue<Runnable>());  
}
//使用    
Executors.newCachedThreadPool().execute(r);

CachedThreadPool只有非核心线程,最大线程数非常大,所有线程都活动时,会为新任务创建新线程,否则利用空闲线程(60s空闲时间,过了就会被回收,所以线程池中有0个线程的可能)处理任务。任务队列SynchronousQueue相当于一个空集合,导致任何任务都会被立即执行。
3、** SingleThreadPool**

public static ExecutorService newSingleThreadPool (int nThreads){
return new FinalizableDelegatedExecutorService (
new ThreadPoolExecutor (1, 1, 0, TimeUnit. MILLISECONDS,
new LinkedBlockingQueue<Runnable>()) );  }
//使用   
 Executors.newSingleThreadPool ().execute(r);

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

public static ScheduledExecutorServicenewScheduledThreadPool(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);

ScheduledThreadPool核心线程数固定,非核心线程(闲着没活干会被立即回收)数没有限制,从上面代码也可以看出,ScheduledThreadPool主要用于执行定时任务以及有固定周期的重复任务。

扫码关注公号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容

  • 线程池的优点: 重用线程池中的线程,避免因为线程的创建和销毁带来的性能消耗 能有效的控制线程的最大并发数,避免大量...
    乆丩乣阅读 5,386评论 5 30
  • 线程池的优点: 1.重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。 2.能有效控制线程池的最大并发...
    铜角大王阅读 131评论 0 0
  • 线程池的好处 (1)重用线程池中的线程,避免因为线程的创建和销毁所带来的性能的开销。(2)能有效控制线程池的最大并...
    蓝枫zeke阅读 354评论 0 2
  • Android 中的四种线程池 在开发中使用线程池的优点 重用线程池中的线程,避免因为线程的创建和销毁带来的性能开...
    任教主来也阅读 182评论 0 0
  • 1、线稿,先把人物主体打形,是个可爱的美少女哦 2.整体造型,画到这时候,发现手有点问题 3、上调子,改一点细节 ...
    西瓜榴莲阅读 199评论 0 2