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>()));
}
网友评论