一、Android中的异步方式
AsyncTask
底层用到了线程池。AsyncTask封装了线程池和Handler
主要是为了方便开发者在子线程中更新UI
AsyncTask内的Handler是一个静态的Handler对象,为了能够将执行环境切换到主线程,这就要求Handler这个对象必须在主线程中创建。由于静态成员会在加载类的时候进行初始化,因此这就变相要求AsyncTask的类必须在主线程中加载,否则同一个进程中的AsyncTask都无法正常工作。
优点:
- 封装了Handler和消息队列,并提供了方便的方法来在后台线程执行任务,并在主线程更新UI。适用于简单的异步操作和UI更新场景
缺点:
- 对于复杂的线程间通信需求,AsyncTask可能无法满足要求。它在执行多个异步任务时可能存在串行执行的问题,并且不适合长时间运行的任务。
注意:
从Android 3.0开始,默认情况下AsyncTask是串行执行的。但在Android 3.0之前是并行执行的
IntentService
IntentService内部采用HandlerThread来执行任务,当任务执行完毕后IntentService会自动退出
特殊的Service,它继承了Service并且它是抽象类。IntentSerice可用于执行后台耗时的任务,当任务执行后它会自动停止,同时由于IntentService是服务的原因,这导致他的优先级比单纯的线程要高很多,所以IntentService比r较适合执行一些高优先级的后台任务
HandlerThread
底层直接使用了线程,是一种消息循环的线程,内部使用Handler
二、线程池
1.使用方式
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory) {...
}
2.参数详解:
- corePoolSize:核心线程数
是指线程池中长期存活的线程数
- maximumPoolSize:最大线程数
是指线程池允许创建的最大线程数量,最大线程数的数量包含核心线程数
当线程池中核心线程都处理执行状态,有新请求的任务时:
工作队列未满:新请求的任务加入工作队列
工作队列已满:线程池会创建新线程,来执行这个任务,创建新线程的数量受到最大线程数的限制 - keepAliveTime:空闲线程存活时间
线程数大于核心线程数时,空闲线程在等待新任务到达的最大时间,如果超过这个时间还没有任务请求,该空闲线程就会被销毁
- util,空闲线程存活时间的单位
keepAliveTime的计量单位。枚举类型TimeUnit类 - workQueue:工作队列
工作队列用于存储待执行的任务。当线程池中的线程都在忙碌时,新提交的任务将被添加到工作队列中等待执行 - threadFactory:线程工厂
用于创建新线程。线程工厂提供了创建线程的方法,可以自定义线程的名称、优先级等属性 - rejectedExecutionHandler:拒绝策略
定义了当线程池无法接受新任务时的处理策略。当工作队列已满且线程池中的线程数已达到最大线程数时,新任务将被拒绝执行。常见的拒绝策略有丢弃、丢弃最旧的任务、抛出异常等
3.作用
限制无限制的创建线程
4.Android常用的线程池
在Executors里面对应的方法:
- FixedThreadPool :固定大小线程池
该线程池维护一个固定数量的线程。无论任务多少,都只会创建固定数量的线程来执行任务。当所有线程都处于忙碌状态时,新任务将被放入队列等待
-
CachedThreadPool :缓存线程池
该线程池根据任务的数量动态调整线程的数量。如果有可用的空闲线程,则会重用它们;如果没有可用的线程,则会创建新的线程。如果线程空闲时间过长,超过一定阈值,那么这些空闲线程将会被终止并移除
-
SingleThreadPool :单个线程池
该线程池只包含一个线程,用于顺序执行所有任务。即使任务异常或终止,也会有新线程取代它。适用于需要按顺序执行任务的场景。
-
ScheduledThreadPool :调度线程池
该线程池用于执行延迟任务或周期性任务。可以指定任务的执行时间或间隔,并由线程池自动触发执行。