线程和线程池
1.AsyncTask
内部封装了Thread
和Handler
,可以在线程池中执行后台任务,然后把任务进度和结果传递给主线程并在主线程中更新UI,不过并不适合执行特别耗时的任务。
2.AsyncTask
是个抽象的泛型类,有三个泛型参数:params
(参数的类型)、progress
(后台任务执行进度的类型)、result
(后台任务返回的类型)。常用用法如下:
AsyncTask<String,Integer,String> asyncTask=new AsyncTask<String, Integer, String>() {
@Override
protected void onPreExecute() {//主线程中执行,做一些准备工作
super.onPreExecute();
}
@Override
protected String doInBackground(String... strings) {//线程池中执行,做耗时操作
//publishProgress用来更新进度,会调用onProgressUpdate方法
publishProgress(3);
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {//主线程中执行,用于更新进度
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String s) {//主线程中执行,任务执行完后返回结果
super.onPostExecute(s);
}
@Override
protected void onCancelled() {//主线程中执行,任务取消的时候调用
super.onCancelled();
}
};
3.使用AsyncTask
需要注意以下几点:
1.AsyncTask必须在主线程初始化,因为内部有Handler必须要在主线程初始化;
2.execute方法必须在主线程调用且同一个AsyncTask对象只能调用一次;
3.不要手动调用AsyncTask的回调方法;
4.Android3.0后AsyncTask采用串行执行任务,要并行可以用executeOnExecutor方法。
4.AsyncTask
的工作原理:调用AsyncTask
的execute
方法→调用executeOnExecutor
方法→调用onPreExecute
方法,然后线程池开始执行→将params
参数封装成FutureTask
对象,并在SerialExecutor
的execute
方法里将FutureTask
对象插入mTask
队列里→如果现在没有正在执行的任务,调用scheduleNext
方法,在scheduleNext
方法里调用THREAD_POOL_EXECUTOR.execute
方法真正执行任务。调用FutureTask
的run
方法时会去调用WorkerRunnable
的call
方法,call
方法会先把mTaskInvoked
设为true
,表示这个任务已经执行过了,然后调用doInBackground
方法,并将其结果值传递给postResult
方法,postResult
方法里面通过handler
发送消息切换到主线程,并调用AsyncTask
的finish
方法,在finish
方法里面调用onPostExecute
方法。
5.IntentService
是一个继承Service
的抽象类,用于执行耗时任务,任务执行完毕后会自动停止,其优点是它是服务,比线程的优先级高,不容易被系统杀死。IntentService
内部封装了HandlerThread
和Handler
,HandlerThread
继承了Thread
,run()
方法里初始化了Looper
并开启了消息循环,IntentService
初始化的时候,会新建一个HandlerThread
对象,并调用其start()
方法,然后获取HandlerThread
的Looper
对象并用来创建Handler
。启动服务的时候,会在onStartCommand
方法中调用onStart
方法,在onStart
方法里通过这个handler
发消息,最后被HandlerThread
调用onHandleIntent
(这里就是我们需要重写并做逻辑处理的地方)处理,如果任务都完了还会调用stopself
方法关闭服务。
6.线程池的优点如下:
1.重用线程,减少线程创建和销毁带来的性能开销。
2.有效控制线程的并发数,防止抢夺系统共享资源造成的阻塞。
3.对线程进行管理,比如定时执行或指定间隔循环等。
7.ThreadPoolExecutor
是Executor
的具体实现,构造方法为:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
corePoolSize
表示核心线程数,默认情况下核心线程是一直存活的,通过ThreadPoolExecutor
的allowCoreThreadTimeOut(ture)
可以让闲置的核心线程在等待新任务超过keepAliveTime
的时候被终止。
maximumPoolSize
表示最大线程数,超过这个数值的线程会被阻塞。
keepAliveTime
表示超时时间,非核心线程闲置时,等待新任务超过这个时间就会被回收。
unit
表示keepAliveTime
的单位。
workQueue
表示任务队列,execute
方法会将一个runnable
对象存储在里面。
threadFactory
表示线程工厂,为线程池提供创建新线程的功能。
8.ThreadPoolExecutor
执行任务的规则如下:
1.核心线程数量未满时创建一个核心线程执行任务。
2.核心线程数量已满,任务插入到任务队列等待执行。
3.如果任务队列无法继续插入,表示任务队列已满,如果线程数量未达到最大线程数量,就开启一个非核心线程来执行任务。
4.如果已经达到最大线程数,就拒绝任务。
9.Android
中常见的四种线程池,返回类型都是ExecutorService
,一般需要强转为ThreadPoolExecutor
,ThreadPoolExecutor
是AbstractExecutorService
的子类,而AbstractExecutorService
实现了ExecutorService
接口:
(1)FixedThreadPool
,通过Executors.newFixedThreadPool()
方法创建。线程数量固定,且都是核心线程,即空闲不会回收。此外,它没有超时限制,任务队列大小是无限制的。
(2)CachedThreadPool
,通过Executors.newCachedThreadPool()
方法创建。线程数量不固定,只有非核心线程,最大线程数为Integer.MAX_VALUE
,有60秒的超时。
(3)ScheduledThreadPool
,通过Executors.newScheduledThreadPool()
方法创建。核心线程数固定,非核心线程数无限制,可以执行定时任务。
(4)SingleThreadExecutor
,通过Executors.newSingleThreadExecutor()
方法创建。只有一个核心线程,所有的任务都在这个核心线程顺序执行。