# 线程

AsyncTask、IntentService、HandlerThread的表现形式都和传统的线程有区别,但本质上仍然是传统的线程。对于AsyncTask来说,底层用到了线程池,对于IntentService和HandlerThread来说,底层则是直接使用到了线程。

  • AsyncTask底层封装了线程池和Handler,主要是为了方便开发者在子线程中更新UI。
  • HandlerThread是一种具有消息循环的线程,在它的内部可以使用Handler。
  • IntentService是一个服务,系统对其进行了封装使其可以更方便地执行后台任务,内部采用HandlerThread来执行任务,当任务执行完毕后会自动退出。

# AsyncTask

AsyncTask在具体的使用过程中也有条件限制:

  • AsyncTask的类必须在主线程中加载,即第一次访问AsyncTask必须发生在主线程;
  • AsyncTask的对象必须在主线程中创建;
  • execute方法必须在UI线程调用;
  • 一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会异常;

# 原理

AsyncTask中有两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(IntentHandler),其中线程池SerialExecutor用于任务的排队,而线程池THREAD_POOL_EXECUTOR用于真正地执行任务。IntentHandler用于将执行环境从线程池切换到主线程。

# IntentService

IntentService是一种特殊的Service,它继承了Service并且是一个抽象类,所以必须构建它的子类才可以使用IntentService。IntentService可用于执行后台耗时的任务,当任务执行完毕后会自动停止。它的优先级比很多单纯的线程要高很多,所以IntentService比较适合执行一些高优先级的后台任务。

IntentService底层是封装了HandlerThread和Handler。

# 线程池的好处、原理、类型

# 好处

在编程中经常会使用线程来异步处理任务,但是每个线程的创建和销毁都需要一定的开销。如果每次执行一个任务都需要开启一个新的线程去执行,则这些线程的创建和销毁将消耗大量的资源;并且线程都是“各自为政”的,很难对其进行控制,这时候就需要线程池来对线程进行管理。

  • 重用线程池中的线程,避免线程的创建和销毁带来的性能消耗;
  • 有效控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源而导致阻塞现象;
  • 进行线程管理,提供定时/循环间隔执行等功能

# 原理

ThreadPoolExecutor是线程池的真正实现。

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
  • corePoolSize核心线程数:一般会在线程中一直存活
  • maximumPoolSize最大线程数:当活动线程数达到这个数值后,后续的任务将会被阻塞
  • keepAliveTime非核心线程超时时间:超过这个时长,闲置的非核心线程就会被回收
  • unit:用于指定keepAliveTime参数的时间单位
  • workQueue任务队列:通过线程池的execute()方法提交的Runnable对象会存储在这个参数中。
  • threadFactory:线程工厂,可创建新线程
  • handler:在线程池无法执行新任务时进行调度

# 分类

  • FixThreadPool:线程数量固定的线程池,所有线程都是核心线程,当线程空闲时不会被回收;能快速响应外界请求。
  • CachedThreadPool:线程数量不定的线程池(最大线程数为Integer.MAX_VALUE),只有非核心线程,空闲线程有超时机制,超时回收;适合于执行大量的耗时较少的任务
  • ScheduledThreadPool:核心线程数量固定,非核心线程数量不定;可进行定时任务和固定周期的任务。
  • SingleThreadExecutor:只有一个核心线程,可确保所有的任务都在同一个线程中按顺序执行;好处是无需处理线程同步问题。

# ThreadPoolExecutor的工作策略 Uncompleted

# Pipeline管道模式 Uncompleted