Android-Threadpool

     关于线程我不想再说什么,感兴趣的同学可以看我之前写过的一篇文章:Android-多线程,这里对线程有一个比较详细的解释。

Android-多线程 - 简书

我们今天直入重点:聊意料我们常用的线程池.

一:

1.什么是线程池?

听名字也不难理解,线程池就是线程的集合,用来控制管理线程,控制并发数等,减少了线程创建和销毁的次数。提高线程的复用率,降低性能的损耗。

2.有哪些线程池呢?

        首先我们先从源码的角度开始分析,先创建一个线程池,然后一步步查看它的源码,分析其关系。

        直接上图:


然后一步步查看:从最上面的接口开始。


首先。Executor是一个类的实现接口,里面有一个执行方法:execute().,这就是线程池的起源,属于线程的一个执行工具,并不是真正的线程池。


如图,我们可以看到ExecutorService接口继承自我们之前的Executor工具类,它里面有好多的api方法,是真正的线程池接口。


然后呢,AbstractExecutorService是一个抽象方法,它实现了ExecutorService接口,可以实现其抽象方法, 也可以进行自定义。


最后ThreadPoolExecutor才是我们的具体实现类,Android中的线程池都是 直接或间接通过配置ThreadPoolExecutor 来实现不同的线程池。

我们来看一下它的构造方法:



  其实ThreadPoolExecutor有四种构造方法,我们举例其中最多的一个讲一下。

(1)  //核心线程数 

int corePoolSize,  

注:线程池新建线程的时候,如果当前线程总数小于 corePoolSize ,则新建的是核心线程;如果超过corePoolSize,则新建的是非核心线程。

(2)  //最大线程数,活动线程数量超过它,后续任务就会自动排队                    

int maximumPoolSize

线程总数= 核心线程数 + 非核心线程数。

(3)    //超时时长,非核心线程如果长时间闲置,超过这个时长便被回收    ,但如果设置allowCoreThreadTimeOut = true,则会作用于核心线程 ,超过时长也会被回收。  

long keepAliveTime,                            

(4)   //枚举类型,设置keepAliveTime的单位,MILLISECONDS : 毫秒 、SECONDS : 秒、MINUTES : 分、HOURS : 小时、DAYS : 天

TimeUnit unit,  

//缓冲任务队列,线程池的execute方法会将Runnable对象存储起来,当所有的核心线程都有活干,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务。

BlockingQueue workQueue,  

(5)  //线程工厂接口,只有一个new Thread(Runnable r)方法,可以认为是线程池创建新线程  

BlockingQueue有四种队列类型:(1)SynchronousQueue:(同步队列)

                                                    (2)LinkedBlockingQueue(链表阻塞队列)

                                                    (3)ArrayBlockingQueue(数组阻塞队列)

                                                    (4)DelayQueue(延迟队列)

SynchronousQueue:(同步队列)这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,但如果所有的线程都在工作呢?这种情况下,SynchronousQueue就会新建一个线程来处理这个任务。所以为了保证不出现(线程数达到了maximumPoolSize而不能新建线程)的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大,去规避这个使用风险。

LinkedBlockingQueue(链表阻塞队列):这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize

ArrayBlockingQueue(数组阻塞队列):可以限定队列的长度(既然是数组,那么就限定了大小),接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误

DelayQueue(延迟队列):队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务

(6)   //创建线程的方式

       ThreadFactory threadFactory  这是一个接口,new它的时候需要实现他的Thread newThread(Runnable r)方法。

(7)   // 这个主要是用来抛异常的,如果线程无法执行新任务一般会抛一个RejectedExecutionException异常。

       RejectedExecutionHandler handler

二:ok,讲完了这些,我们来看看如何使用线程池?


线程池新添加了任务,那么线程池是如何运行的呢,总结:

1:如果线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务

2:如果线程数量达到了corePools,则将任务移入队列等待

3:如果队列已满,新建线程(非核心线程)执行任务

4:如果队列已满,总线程数又达到了maximumPoolSize,就会由RejectedExecutionHandler抛出异常


但我们不需要这么费劲,java已经给我们提供了四种线程池,,来搞一下。

第一种:

A:定长线程池  newFixedThreadPool ,只有核心线程,数量固定,不会被回收。可控制线程最大并发数,超出的线程会在队列中等待。其中nThreads参数是我们要创建几个线程。如果所有线程都出于运行状态,提交额外的任务,他们会在队列中等待,直到有一个线程可用为止。

使用:


第二种:

B:缓存线程池 newCacheThreadPool,只有非核心线程,最大线程数不做限制,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。空闲线程超过60秒会被终止并从线程池里移除缓存。

使用:


第三种:

C:定长任务线程池,ScheduledExecutorService.支持定时及周期性任务执行

corePoolSize 参数是指在池中保留的线程数,即使它们是空闲的。这个函数最终会返回一个新创建的调度线程池.

使用:


第四种:

    D:newSingleThreadExecutor 创建一个单线程的线程池,用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个单独的线程终止是因为在执行前异常或者终止,若需要执行后续的任务,那么就需要一个新的去替代它,返回的是一个重新创建的单线程去执行。

使用:

突然觉得直接写用法,不来个demo,是不是小伙伴不容易理解呀。那好。我们以缓存线程池为例.来个场景演示。大家都知道下载文件吧,我们就整这个。多线程下载多个文件。

    上一波图:

        咳咳,初始化UI就.......省了吧。




效果:


点击下载文件可以看到是同一个线程池,两个线程平行。


文件A和文件C是同一个线程在下载,也就是在线程thread-1下载文件A完毕后,点击下载文件C,并没有在重新在创建线程,而是复用了文件A下载的thread-1继续下载文件C。

好了就这么多,拜拜。

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

推荐阅读更多精彩内容