Android线程池的选择纠结症

为啥非得要线程池,new Thread().start()。用的如此的爽

1.线程池的选择主要是线程的复用,减少线程的创建和销毁带来的开销;

2.控制线程的并发数,当大量线程争夺cpu资源的时候容易造成阻塞;

3.当然线程池能更好管理这些脱缰的线程们;


无论什么样的线程,最终肯定跑不掉老祖宗ThreadPoolExecutor,先认识一下

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)
最主要的就是核心线程数了,讨论一下核心线程和当前任务数量(currentSize)的效果

1.当currentSize<corePoolSize时,没什么好说的,直接启动一个核心线程并执行任务;
2.当currentSize>=corePoolSize、并且workQueue未满时,添加进来的任务会被安排到workQueue中等待执行;
3.当workQueue已满,但是currentSize<maximumPoolSize时,会立即开启一个非核心线程来执行任务。
4.当currentSize>=corePoolSize、workQueue已满、并且currentSize>maximumPoolSize时,调用handler默认抛出RejectExecutionExpection异常。

workQueue未满只会用核心线程,等待也无妨,满了就需要找帮手非核心线程来处理,就是这么犟



到了新一代的实战型线程池了

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

FixThreadPool(固定大小线程池)

SingleThreadExecutor(单个线程池)

CachedThreadPool(缓存线程池)

ScheduleThreadPool(定时线程池)


1.大公子FixThreadPool

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

1.看的出来其核心线程数和最大线程数是相等的,也就是只有核心线程,数量固定可传。因为都是核心线程所有线程都是活跃的,因为队列没有限制大小,所以新任务会等待;
2.一堆任务抢占资源,可以有无数个排队,能使用资源的就nThreads个。就是任务都执行完毕了,也不会销毁;
3.由于都是核心线程,FixThreadPool能快速响应外界请求。


2.二公子SingleThreadPool

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

1.只有一个核心线程,而且只允许有一个线程,确保所有的任务都在同一个线程顺序完成,不需要处理同步问题;


3.三公子CachedThreadPool

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

1.CachedThreadPool只有非核心线程,最大线程非常大,所有线程都活动时,会为新任务创建新的线程,否则复用空闲的线程,有60s的空闲时间,过了就会被系统回收,所以存在0线程的可能;
2.适合大量耗时较少的任务。


3.四公子ScheduledThreadPool

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.执行定时任务以及有固定周期的重复任务。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 为什么使用线程池 当我们在使用线程时,如果每次需要一个线程时都去创建一个线程,这样实现起来很简单,但是会有一个问题...
    闽越布衣阅读 4,327评论 10 45
  • 第一部分 来看一下线程池的框架图,如下: 1、Executor任务提交接口与Executors工具类 Execut...
    压抑的内心阅读 4,297评论 1 24
  • 函数的执行依赖于作用域,这个作用域在函数定义时决定的,而不是函数调用时决定的; 闭包的概念:函数内部定义了嵌套函数...
    2018_ieye阅读 188评论 0 0
  • 这是一篇很无厘头的文字,就是一些零零散散的话是那种想到什么就说什么的杂文。 两条平行线同时平行划过就会有相交的那一...
    kevinsn阅读 560评论 0 1
  • 代码样例 编译结果 @Mapper 注解的 componentModel 属性 用于指定自动生成的接口实现类的组件...
    mibro阅读 1,727评论 0 1