别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述Android多线程模型相关的知识,希望能为你提供帮助。
作为开发者,我们都知道在开发过程中遇到耗时操作那是不可避免的,例如网络请求、文件读写、数据库操作等等。android是单线程模型,这意味着Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。但是Android在UI操作上也做了时间限制,Activity
——>
5s 、BroadcastReceiver / ContentProvider
——>
10s 、 Service
——>
20s,超过这个时间就会报ANR。所以为了避免ANR,我们会开辟新的线程去做这些操作。对于开辟新线程,如果你还是通过 new Thread 的方式去做,那我觉得应该改变了。先不说这样的方式对内存、资源的消耗有多大,有些机型是对一个应用开辟的线程数量是有限制的,超过了就 over了。所以针对这些情况去了解一下Android中的多线程操作还是非常重要的。
Android提供了四种常用的操作多线程的方式,分别是:
1. Handler+Thread
2. AsyncTask
3. ThreadPoolExecutor
4. IntentService
1. Handler+Thread
Android主线程包含一个消息队列(MessageQueue),该消息队列里面可以存入一系列的Message或Runnable对象。通过一个Handler你可以往这个消息队列发送Message或者Runnable对象,通过Looper负责管理线程的消息队列和消息循环,然后处理这些对象。每次你新创建一个Handle对象,它会绑定于创建它的线程(也就是UI线程)以及该线程的消息队列,从这时起,这个handler就会开始把Message或Runnable对象传递到消息队列中,并在它们出队列的时候执行它们,回调 Handler的handlerMessage() 方法。所以Handler流程中,关键的角色:MessageQueue 、 Looper 、Message/Runnable .优缺点:
1. Handler用法简单明了,可以将多个异步任务更新UI的代码放在一起,清晰明了
2. 处理单个异步任务代码略显多
【Android多线程模型】适用范围:
1. 多个异步任务的更新UI
2. AsyncTask
AsyncTask通过一个阻塞队列BlockingQuery<
Runnable>
存储待执行的任务,利用静态线程池THREAD_POOL_EXECUTOR提供一定数量的线程,默认128个。在Android 3.0以前,默认采取的是并行任务执行器,3.0以后改成了默认采用串行任务执行器,通过静态串行任务执行器SERIAL_EXECUTOR控制任务串行执行,循环取出任务交给THREAD_POOL_EXECUTOR中的线程执行,执行完一个,再执行下一个。看一下示例代码:
class DownloadTask extends AsyncTask< Integer, Integer, String> {
// AsyncTask< Params, Progress, Result> //后面尖括号内分别是参数 @Override protected void onPreExecute() { //第一个执行方法 super.onPreExecute(); }@Override protected String doInBackground(Integer... params) {
//第二个执行方法,onPreExecute()执行完后执行return "执行完毕"; }@Override protected void onProgressUpdate(Integer... progress) {
//显示进度super.onProgressUpdate(progress); }@Override protected void onPostExecute(String result) {
//doInBackground返回时触发,换句话说,就是doInBackground执行完后触发super.onPostExecute(result); } }
通过示例代码,我们知道AsyncTask重要的几个方法: onPreExecute() 、doInBackground(Integer... params) 、onProgressUpdate(Integer... progress)、onPostExecute(String result) 。这四个方法中onProgressUpdate 默认是不会触发的,需要通过对象调用publishProgress() 方法才被调用。
优缺点:
1. 处理单个异步任务简单,可以获取到异步任务的进度
2. 可以通过cancel方法取消还没执行完的AsyncTask
3. 处理多个异步任务代码显得较多
适用范围:
1. 单个异步任务的处理
3. ThreadPoolExecutor
ThreadPoolExecutor提供了一组线程池,可以管理多个线程并行执行。这样一方面减少了每个并行任务独自建立线程的开销,另一方面可以管理多个并发线程的公共资源,从而提高了多线程的效率。所以ThreadPoolExecutor比较适合一组任务的执行。但是我们这里强制不允许使用Executor去创建线程池,而是通过ThreadPoolExcutor的方式,规避资源耗尽的风险。
说明:
1) FixedThreadPool 和 SingleThreadPool : 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM;
2) CachedThreadPool 和 ScheduledThreadPool : 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
所以正确方式:(更详细的开发规范,点击这里)
int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors(); int KEEP_ALIVE_TIME = 1; TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS; BlockingQueue< Runnable> taskQueue = new LinkedBlockingQueue< Runnable> (); ExecutorService executorService = new ThreadPoolExecutor(NUMBER_OF_CORES, NUMBER_OF_CORES*2, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, taskQueue, new BackgroundThreadFactory(), new DefaultRejectedExecutionHandler());
适用范围
1. 批处理任务
4. IntentService
IntentService继承自Service,是一个经过包装的轻量级的Service,用来接收并处理通过Intent传递的异步请求。客户端通过调用startService(Intent)启动一个IntentService,利用一个work线程依次处理顺序过来的请求,处理完成后自动结束Service。避免在BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时操作,应该创建IntentService完成,而不应该在BroadcastReceiver内创建子线程去做。特点
1. 一个可以处理异步任务的简单Service
参考:
https://www.jianshu.com/p/2b634a7c49ec
https://www.cnblogs.com/chendu123/p/6081301.html
推荐阅读
- APP定制开发的准备事项
- Android--Android studio --Button点击事件的写法
- Android-LinearLayout
- OpenCV读取并保存图像
- Win10系统语言“删除”按钮灰色无法点击该怎样办?
- Win10电脑如何设置开机密码?
- Win10镜像怎样安装?
- Win10系统如何打开Hyper-V虚拟机?
- Win10怎样打开.ceb格式的文件?