android 如何阻塞线程池,Android中的线程池-应用场景分析笔记

我吐了,老忘点边边脚脚 好记性不如烂笔头!

线程池的作用

1.重用线程池中的线程,减少线程的创建和销毁带来的开销

2.有效的控制线程的最大并发数,避免大量线程之间因为相互抢占系统资源而导致的阻塞现象。

3.提供简单的管理,定时执行,指定间隔循环执行,线程资源常驻及释放

线程池的配置

Android中线程池的概念来源于java中的Executor,具体实现为 ThreadPoolExecutor。可以通过它的构造参数来创建不同类型的线程池。

构造参数详细

对参数作用充分理解后,方便后面对默认提供的四种线程池的应用场景的分析

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)复制代码

1.corePoolSize 核心线程最大数量

情况1:allowCoreThreadTimeout = flase(默认),核心线程会伴随线程池的整个生命周期一直存活,即使处于闲置

情况2:allowCoreThreadTimeout = true,闲置的核心线程在等待新任务时可触发超时策略,时间间隔为keepAliveTime

2.maximumPoolSize 线程池能容纳的最大线程数

当活动线程数量达到这个值以后,后续的新任务将会被阻塞(进度阻塞队列,等待绑定执行)

3.keepAliveTime 非核心线程闲置的超时时长(在1中情况2时也会作用于核心线程)

闲置线程等待任务超过这个时长,将会被回收。

4.unit keepAliveTime 的单位

可以使用毫秒,秒,分钟

5.workQueue

线程池的任务队列,通过线程池的execute方法提交的Runnable对象会存储在这个参数中。

6.threadFactory

线程工厂,为线程池提供创建新线程的功能的接口。

RejectedExecutionHandler 拒绝执行的回掉

当线程池无法执行新任务时,任务队列已满或是无法成功执行任务。

合理配置参数

参考AsyncTask,但是这并不是一个固定指标。

AsyncTask的线程池配置如下:

核心线程数=CPU核心数+1

线程池最大线程数=CPU核心数量*2+1

核心线程无超时,非核心线程闲置超时时间=1s

任务队列容量为128

复制代码

ThreadPoolExecutor 线程创建规则

1.如果线程池中的线程数量未达到核心线程的数量,则直接启动一个核心线程来执行任务。

2.如果线程池中的数量>=核心线程数量,那么任务将会被插入任务队列中,排队等待执行

3.如果2中无法将任务插入到任务队列中(正常情况下任务队列已满),此时如果线程总数(核心+非核心)<=线程池配置的最大线程数,则启动一个非核心线程来执行任务

4.如果3中线程总数量已达到线程池配置的最大线程数量,则拒绝执行此任务,回调RejectedExecutionHandler的rejectedExecution方法。

线程池的分类应用

SDK提供了4中常用线程池,分别适应不同的应用场景。FixedThreadPool,CachedThreadPool,ScheduledThreadPool,SingleThreadExecutor

FixedThreadPool 核心版

public static ExecutorService newFixedThreadPool(int nThreads){

return new ThreadPoolExecutor(nThreads, nThreads,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue());

}

复制代码

核心线程数量=最大线程数量,超时时间=0。所以这个线程池只有核心线程,而且核心线程不会超时。一个吞吐量固定,长期营业的线程池。

优点:响应任务的速度快,任务量与吞吐量饱和时,任务处理效率最大化。

缺点:并发能力较弱,吞吐量>任务数量时不可避免会造成资源浪费(主要是内存)。

应用场景:处理需要长期快速响应,无很高的并发效率要求。对批量任务执行无较高的时间等待要求。

CachedThreadPool 裸奔版本

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory){

return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

60L, TimeUnit.SECONDS,

new SynchronousQueue(),

threadFactory);

}

复制代码

没有核心线程,只有非核心线程 数量=Integer.MAX_VALUE。超时时间60s,无缓存任务队列(SynchronousQueue:简单理解为一个无法存储元素的队列)

优点:所有任务都会被立即分配线程执行,几乎可以理解为一个突破手。用于处理集中并发任务。在全部线程都超时后,这个线程池几乎是不占任何系统资源的(我将这里类比为主动new N个普通线程)

缺点:随着任务数量激增可能会导致系统资源匮乏,导致线程阻塞。

应用场景:处理大量耗时较少的任务

ScheduledThreadPool 调度版

public ScheduledThreadPoolExecutor(int corePoolSize,

ThreadFactory threadFactory){

super(corePoolSize, Integer.MAX_VALUE,

DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,

new DelayedWorkQueue(), threadFactory);

}

public ScheduledFuture> schedule(Runnable command,

long delay, TimeUnit unit);

复制代码

非核心线程数量Integer.MAX_VALUE,闲置线程等待超时10s。

优点:非核心线程10s就会被即时回收,释放速度快,吞吐量大于FixedThreadPool

响应速度略高于CachedThreadPool。

缺点:这是一个非极端的线程池,缺点不明显

应用场景:使用schedule()方法处理定时任务,或处理固定周期的重复任务,执行完后直到下次执行期间,尽量少的占用资源。可以参考这个配置自定义线程池,更好的适应具体场景,比如将DEFAULT_KEEPALIVE_MILLIS 设置为0s,加速资源释放。

SingleThreadExecutor 单实例版

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory){

return new FinalizableDelegatedExecutorService

(new ThreadPoolExecutor(1, 1,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue(),

threadFactory));

}

复制代码

就一个核心线程,没有非核心线程,队列使用LinkedBlockingQueue。毫无疑问这是个任务队列+单线程的顺序执行的“任务池”。

应用场景:处理需要按顺序执行的任务。

END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值