当我们启动app的时候,android系统就会启动一个Linux Process,这个Process包含一个UI Thread,这个线程处理很多重要的逻辑,如系统事件处理、用户输入事件、UI绘制、Service、Alarm等,入下图:
而我们编写的代码就穿插在这些逻辑中间,比如对用户触摸事件的检测和响应,自定义View的绘制。如果我们进行耗时的操作,如网络请求、数据库读取,就会阻塞到UI线程的其他逻辑的执行,从而导致页面的卡顿。所以我们执行耗时的操作的时候,都是需要在另外的线程执行。
Android 提供了四种常用的操作多线程的方式
Handler+Thread AsyncTask ThreadPoolExecutor IntentService
1 . Handler + Thread
Android主线程包含一个消息队列(MessageQueue),通过Handler可以向该消息队列推送Message(消息)或Runnable对象。每次新创建一个Handler对象,它会绑定于创建它的线程以及该线程的消息队列,
Handler传递消息的两种方式:Post和SendMessage
Post
对于Handler的Post方法来说,它会传递一个Runnable对象到消息队列中,在这个Runnable对象中,重写run()方法。一般来说这个run()方法中写入需要在Ui Thread的操作
sendMessage
Handler使用sendMessage需要传递Message对象,而在Handler中,需要重写handleMessage方法,用户获取耗时线程传递过来的消息。
2 . AsyncTask
AsyncTask是android的一个异步类,可以直接继承AsyncTask使用,在类中实现异步操作,并提供反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后返回执行结果给UI Thread
3 . ThreadPoolExecutor
ThreadPoolExecutor 提供一组线程池,可以管理多个线程并执行。一方面减少每个并行任务独立创建线程的开销,另一方面可以管理多个并发线程的公共资源,从而提高多线程效率。比较适用于一组任务的执行。
Executors 利用工厂模式对ThreadPoolExecutor进行封装,并提供四种创建ExecutorService的方法
1. Executors.newFixedThreadPool() 创建一个定长的线程池,每提交一个任务就创建一个线程,直到达到池的最大长度,这时线程池会保持长度不再变化
2. Executors.newCachedThreadPool() 创建一个可缓存的线程池,如果当前线程池的长度超过了处理的需要时,它可以灵活的回收空闲的线程,当需要增加时, 它可以灵活的添加新的线程,而不会对池的长度作任何限制
3. Executors.newScheduledThreadPool() 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer
4. Executors.newSingleThreadExecutor() 创建一个单线程化的executor,它只创建唯一的worker线程来执行任务
4 . IntentService
IntentService继承自Service,是一个经过包装的轻量级的Service,用来接收并处理通过Intent传递的异步请求。客户端通过调用startService(Intent)启动一个IntentService,利用一个work线程依次处理顺序过来的请求,处理完成后自动结束Service。