Android必备知识之线程和线程池
主线程处理页面交互逻辑(运行四大组件和处理它们和用户的交互),具有较高的响应速度,不能做耗时操作,所以需要子线程。3.0之后,如果在主线程做联网耗时操作,报NeworkOnMainThreadException异常。
1.AsyncTask 128
轻量级的异步任务类,封装了Thread和Handler它可以在线程池中执行后台任务,然后把执行进度和结果传递给主线程。不适合执行特别耗时的操作
class AsyncTask<Params, Progress, Result>
AsycnTask提供4个核心方法:
1.onPreExcecute()
2.doInBackground(Params…params)
3.onProgressUpdate(Progress…values)
4.onPostExecute(Result result)
2.HandlerThread
HandlerTread继承Thread,是一种可以使用Handler的Thread.
它的实现是:在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。
和普通Thread的不同:普通Thread在run方法中执行一个耗时任务,HandlerThread在内部创建了消息队列,外界需要通过Handler的消息方式通知HandlerThread执行一个具体的任务。
需要注意的点:HandlerThread的run方法是一个无限循环,当不再使用时,需要通过quit或者quitSafely关闭。
prepare()呢,中创建了一个Looper对象,并且把该对象放到了该线程范围内的变量中(sThreadLocal),在Looper对象的构造过程中,初始化了一个MessageQueue,作为该Looper对象成员变量。
loop()就开启了,不断的循环从MessageQueue中取消息处理了,当没有消息的时候会阻塞,有消息的到来的时候会唤醒。
3.Android中的线程池ThreadPoolExecutor
<1>线程池的优点:
重用线程池中的线程,避免因为线程的创建和销毁带来的性能消耗
能有效的控制线程的最大并发数,避免大量的线程之间因抢占系统资源而导致的阻塞现象
能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能
<2>代码
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize
程池中的核心线程数
maximumPoolSize
最大线程池大小,当活动线程数达到这个值,后续任务会被阻塞
keepAliveTime
线程池中超过corePoolSize数目的非核心线程最大存活时间;闲置时的超时时长,超过这个值后,闲置线程就会被回收
unit
keepAliveTime 参数的时间单位。这是一个枚举
workQueue
执行前用于保持任务的队列,也就是线程池的缓存队列。此队列仅保持由 execute 方法提交的 Runnable
<3>四种线程池
1.FixedTreadPool
通过工厂方法类Executors的newFixedThreadPool方法创建。它是线程数量固定的线程池,仅有核心线程且没有超时策略,所以线程不会被回收。这意味着它能够快速的响应外界请求。
Runnable runnable = new Runnable() {
@Override
public void run() {
Log.d("tag","sleep前");
SystemClock.sleep(2000);
Log.d("tag", "sleep后");
}
};
......
ExecutorService executorService = Executors.new FixedThreadPool(4);
executorService.execute(runnable);
executorService.execute(runable1);
executorService.execute(runable2);
executorService.execute(runable3);
结果:一次性执行四个前,然后四个后
2.CachedThreadPool
它是一种线程数量不定的线程池,只有非核心线程,可以简单理解为最大线程数是无限大的。CachedThreadPool的任务队列相当于一个空集合,这导致任何任务都会被立即执行,比较适合做一些大量的耗时较少的任务。
ExecutorService executorService = Executors.newCachedThreadPool();
3.ScheduledThreadPool
Scheduled有 “预定的” 意思。核心线程池的数量书固定的且非核心线程池是没有限制的,非核心线程池被闲置时会被立即回收。主要用于执行定时任务和具有固定周期的重复任务。
延迟1000秒执行
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
scheduledExecutorService.schedule(runnable,1000, TimeUnit.MILLISECONDS);
scheduledExecutorService.schedule(runable1, 1000, TimeUnit.MILLISECONDS);
scheduledExecutorService.schedule(runable2, 1000, TimeUnit.MILLISECONDS);
scheduledExecutorService.schedule(runable3, 1000, TimeUnit.MILLISECONDS);
//延迟10ms后开始每1000ms执行一次runnable。
scheduledExecutorService.scheduleAtFixedRate(runnable,10,1000,TimeUnit.MILLISECONDS);
4.SingleThreadExecutor
只有一个核心线程,所以确保所有的任务都是在一个线程里顺序执行。把所有的任务都放到一个线程,这样有一个好处是不需要处理线程同步问题。排着队依次执行,且不会乱序。