Android 中的四种线程池
在开发中使用线程池的优点
-
重用线程池中的线程,避免因为线程的创建和销毁带来的性能开销
开辟一块内存空间,存放许多未死亡的线程,池中线程执行调度有池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样就可以避免反复创建线程对象所带来的性能开销,节省了系统的资源
能有效控制线程池的最大并发数,避免大量的线程之间因为互相抢占系统资源而导致的阻塞现象
能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。
Android 中的线程池
Android 中的线程概念来源于 Java 中的 Executor ,Executor 是一个接口,其子接口是 ExecutorService,最终 ThreadPoolExecutor 实现了该接口并提供了一系列参数来配置线程池。
启动:调用线程池对象的 execute(Runnable r) 启动,Runnable 的 run 方法会运行在子线程,以及 ScheduleThreadPool 的 schedule 延迟执行,和 scheduleAtFixedRate 方法,延迟一段时间执行并每隔一段时间执行一次
停止:shutdown 不会立即停止,等待缓冲队列中的任务执行完成后停止,并不在接收新的任务
shutdownNow 立即终止,并打断正在执行的任务,清空缓冲队列,返回未执行的任务
ThreadPoolExcutor 的构造方法中的参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
corePoolSize 线程池维护线程的最小数量,一般设置等于 CPU 核数 + 1,添加任务时,如果线程池中的数量小于 corePoolSize ,不管线程池中的线程是否处于空闲状态,都会创建新的线程来处理被添加的任务
maximumPoolSize 线程池维护线程的最大数量,一般设置等于 CPU 核数的两倍再加 1 ,添加任务时,如果线程池中的数量等于 corePoolSize ,并且 workQueue 已满,会创建新的线程来处理被添加的任务
keepAliveTime 设置非核心线程等待的超时时间 unit 超时时间单位的枚举表示,如果 allowCoreThreadTimeOut() 设置为 true ,则核心线程也会有超时时间,默认核心线程无超时时间
workQueue 线程池所使用的缓冲队列,添加任务时,如果线程池中的数量等于 corePoolSize ,但是 workQueue 未满,那么任务被放入缓冲队列,一般设置为 128 ,超出时会调用相应的 Handler (并不是Android 中的Handler) 来处理,默认为抛出拒绝异常,RejectedExecutionHandler 抛出 rejectedExecution
缓冲队列的大小一般设置为 128 ,添加超出时会安装该线程池设置的处理方式处理,默认为抛出拒绝异常
ThreadFactory 作用为为线程池创建 Thread
常用线程池的分类
通过 Executors 的一系列 new 静态方法获取不同类型的线程池
一、FixedThreadPool
- 是一种线程数固定的线程池,当线程处于空闲状态时,不会被回收,除非线程池关闭了。当所有的线程都处于活动状态时,新任务都会处于等待状态,知道有线程空闲出来。
- 只有核心线程没有非核心线程,优点是响应速度更快。
- 没有超时机制,任务队列也没有大小限制
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
二、CachedThreadPool
- 是一种现场数量不定的线程池,只有非核心线程,并且最大线程数量为 Integer.MAX_VALUE
- 当线程池中的线程都处于活动状态时,线程池会创建新的线程来处理任务,否则会利用空闲线程来处理任务
- 线程池中的空闲线程都有超时机制,为60秒,超过60秒空闲的线程就会被回收
- 任务队列 SynchronousQueue 是无法插入任务的,说明所有任务都会被立即执行
- 适合执行大量的耗时较少的任务
- 当整个线程池都处于闲置状态时,线程池中的线程都会超时而被停止,这时候 CachedThreadPool 中实际是没有任何线程的,几乎不占任何系统资源
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
三、ScheduledThreadPool
- 它的核心线程数量固定,非核心线程数量无限制
- 当非核心线程限制时立即回收
- 适合执行具有固定周期的重复任务
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
四、SingleThreadExecutor
- 只有一个核心线程,确保所有任务都在同一线程中按顺序执行
- 意义在于同一所有的外界任务到一个线程中,这使得这些任务之间不需要处理线程同步问题
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}