前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android-Threadpool

Android-Threadpool

作者头像
android_薛之涛
发布2018-09-11 17:35:46
4400
发布2018-09-11 17:35:46
举报
文章被收录于专栏:Android-薛之涛

关于线程我不想再说什么,感兴趣的同学可以看我之前写过的一篇文章: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。

好了就这么多,拜拜。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.07.14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档