Android多线程方案
为主线程减轻负的多线程方案有哪些呢?这些方案分别适合在什么场景下使用?
Android系统为我们提供了若干组工具类来帮助解决这个问题。
- AsyncTask: 为UI线程与工作线程之间进行快速的切换提供一种简单便捷的机制。适用于当下立即需要启动,但是异步执行的生命周期短暂的使用场景。
 - HandlerThread: 为某些回调方法或者等待某些任务的执行设置一个专属的线程,并提供线程任务的调度机制。
 - ThreadPool: 把任务分解成不同的单元,分发到各个不同的线程上,进行同时并发处理。
 - IntentService: 适合于执行由UI触发的后台Service任务,并可以把后台任务执行的情况通过一定的机制反馈给UI。
 
1. HandlerThread
Android系统为我们提供了Looper,Handler,MessageQueue来帮助实现上面的线程任务模型:
Looper: 能够确保线程持续存活并且可以不断的从任务队列中获取任务并进行执行。
Handler: 能够帮助实现队列任务的管理,不仅仅能够把任务插入到队列的头部,尾部,还可以按照一定的时间延迟来确保任务从队列中能够来得及被取消掉。
MessageQueue: 使用Intent,Message,Runnable作为任务的载体在不同的线程之间进行传递。
把上面三个组件打包到一起进行协作,这就是HandlerThread
程序被启动,系统会帮忙创建进程以及相应的主线程,而这个主线程其实就是一个HandlerThread。这个主线程会需要处理系统事件,输入事件,系统回调的任务,UI绘制等等任务,为了避免主线程任务过重,我们就会需要不断的开启新的工作线程来处理那些子任务。
HandlerThread比较合适处理那些在工作线程执行,需要花费时间偏长的任务。我们只需要把任务发送给HandlerThread,然后就只需要等待任务执行结束的时候通知返回到主线程就好了。
特点:
(1)  HandlerThread将loop转到子线程中处理,分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
(2)  HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
(3)  处理任务是串行执行,按消息发送顺序进行处理。由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那       么就会导致后续的任务都会被延迟处理。
(4)  对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。
2. AsyncTask
使用AsyncTask需要注意的问题有哪些呢?请关注以下几点:
(1) 默认情况下,所有的AsyncTask任务都是被线性调度执行的,他们处在同一个任务队列当中,按顺序逐个执行。
为了解决上面提到的线性队列等待的问题,我们可以使用AsyncTask.executeOnExecutor()强制指定AsyncTask使用线程池并发调度任务。
(2) 其次,如何才能够真正的取消一个AsyncTask的执行呢?
我们知道AsyncTaks有提供cancel()的方法,但是这个方法实际上做了什么事情呢?线程本身并不具备中止正在执行的代码的能力,为了能够让一个线程更早的被销毁,我们需要在doInBackground()的代码中不断的添加程序是否被中止的判断逻辑。
一旦任务被成功中止,AsyncTask就不会继续调用onPostExecute(),而是通过调用onCancelled()的回调方法反馈任务执行取消的结果。我们可以根据任务回调到哪个方法(是onPostExecute还是onCancelled)来决定是对UI进行正常的更新还是把对应的任务所占用的内存进行销毁等。
(3) 最后,使用AsyncTask很容易导致内存泄漏,在Activity内部定义的一个AsyncTask,它属于一个内部类,该类本身和外面的Activity是有引用关系的,如果Activity要销毁的时候,AsyncTask还仍然在运行,这会导致Activity没有办法完全释放,从而引发内存泄漏。
3. ThreadPoolExecutor
Runtime.getRuntime().availableProcesser()方法并不可靠,他返回的值并不是真实的CPU核心数,因为CPU会在某些情况下选择对部分核心进行睡眠处理,在这种情况下,返回的数量就只能是激活的CPU核心数。
使用线程池ThreadPool的好处:
(1)  重用已经创建好的线程,避免频繁创建进而导致的频繁GC
(2)  控制线程并发数,合理使用系统资源,提高应用性能
(3)  可以有效的控制线程的执行,比如定时执行,取消执行等
4. IntentService
默认的Service是执行在主线程的,可是通常情况下,这很容易影响到程序的绘制性能(抢占了主线程的资源)。除了前面介绍过的AsyncTask与HandlerThread,我们还可以选择使用IntentService来实现异步操作。IntentService继承自普通Service同时又在内部创建了一个HandlerThread,在onHandlerIntent()的回调里面处理扔到IntentService的任务。所以IntentService就不仅仅具备了异步线程的特性,还同时保留了Service不受主页面生命周期影响的特点。
正在运行的IntentService的程序相比起纯粹的后台程序更不容易被系统杀死,该程序的优先级是介于前台程序与纯后台程序之间的.
5. 线程优先级
Android系统会根据当前运行的可见的程序和不可见的后台程序对线程进行归类,划分为forground的那部分线程会大致占用掉CPU的90%左右的时间片,background的那部分线程就总共只能分享到5%-10%左右的时间片。默认情况下,新创建的线程的优先级默认和创建它的母线程保持一致。如果主UI线程创建出了几十个工作线程,这些工作线程的优先级就默认和主线程保持一致了,为了不让新创建的工作线程和主线程抢占CPU资源,需要把这些线程的优先级进行降低处理,这样才能给帮组CPU识别主次,提高主线程所能得到的系统资源。
我们可以通过android.os.Process.setThreadPriority(int)设置线程的优先级,参数范围从-20到24,数值越小优先级越高。
Android系统里面的AsyncTask与IntentService已经默认帮助我们设置线程的优先级,
AsyncTask: Process.THREAD_PRIORITY_BACKGROUND
IntentService: Process.THREAD_PRIORITY_DEFAULT
6. 问题
在Activity不停的创建与销毁的过程当中,很有可能因为工作线程持有Activity的View而导致内存泄漏(因为工作线程很可能持有View的强引用,另外工作线程的生命周期还无法保证和Activity的生命周期一致,这样就容易发生内存泄漏了).
Loader的出现就是为了确保工作线程能够和Activity的生命周期保持一致,同时避免出现前面提到的问题。
在Activity或者Fragment中使用Loader可以方便的实现异步加载的框架,Loader有诸多优点。
Android多线程方案的更多相关文章
- Android多线程----异步消息处理机制之Handler详解
		
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
 - Andoid 更好的Android多线程下载框架
		
概述 为什么是更好的Android多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先聊聊我们框架的特点: 多线程 多任务 断点续传 支持大文件 可以自定义下载数据库 高度 ...
 - 更好的Android多线程下载框架
		
/** * 作者:Pich * 原文链接:http://me.woblog.cn/ * QQ群:129961195 * Github:https://github.com/lifengsofts */ ...
 - android 多线程
		
本章讲述在android开发中,多线程的应用.多线程能够处理耗时的操作并优化程序的性能.本章主要介绍知识点,AsyncTask,Java线程池,ThreadPoolExecutor线程池类.本章案例只 ...
 - Android多线程分析之五:使用AsyncTask异步下载图像
		
Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...
 - Android多线程分析之四:MessageQueue的实现
		
Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...
 - Android多线程分析之三:Handler,Looper的实现
		
Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...
 - Android多线程分析之二:Thread的实现
		
Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多线程分析之一 ...
 - Android多线程分析之一:使用Thread异步下载图像
		
Android多线程分析之一:使用Thread异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 打算整理一下对 Android F ...
 
随机推荐
- 博客图片上传picgo工具安装配置github图传使用
			
摘要 对于每一个写博客的人来说,图片是至关重要.这一路经历了多次图片的烦恼,之前选择了微博个人文章那里粘贴图片的方式上传,感觉也挺方便的.但是由于新浪的图片显示问题,如果header中不设置 标签就不 ...
 - sort_values()和sort_index()函数
			
sort_values() 1 可用于对dateframe的多列同时进行排序 True是升序,False是降序,默认是升序 kk.sort_values(by=['listing_id','order ...
 - 红米4高配版 qusb bulk     unknow device   不加电,不亮灯,没反应的 黑砖 的维修方法
			
unknow device处理 1. 按住按住音量减键和开机键3分钟左右 (我按了10秒左右,就成功了.) unknow device 就变qualcomm hs-usb qdloader 9008 ...
 - selenium验证码处理之cookie登录
			
在实际测试中会经常见到登录操作需要验证码验证登录 常见验证有以下几种: 验证码登录 图片识别 图片滑块识别验证 4.简单验证码计算 针对上面的登录验证解决办法有以下几种: 1.让开发去掉验证码 ...
 - State Function Approximation: Linear Function
			
In the previous posts, we use different techniques to build and keep updating State-Action tables. B ...
 - 20191105 《Spring5高级编程》笔记-第11章
			
第11章 任务调度 任务调度由三部分组成: 任务:需要在特定时间运行或定期运行的业务逻辑块: 触发器:指定任务应该执行的条件: 调度程序:根据来自触发器的信息执行任务: 11.2 Spring中的任务 ...
 - powerdisigner
 - 在WebStorm中使用editorConfig插件
			
在webStorm中默认是支持editorConfig插件的,那么我们需要在webStorm中自定义editorConfig的配置怎么来做? 第一步:打开webStrome > File > ...
 - uve (mui/light7)写APP的使用心得(大坑);
			
话说mui这个框架的UI确实挺好看的(个人觉得)所以项目使用了他,结果里面的坑太TM多,不得不说MUI做东西太不用心了,社区不活跃,提问都没人管!; mui第一个坑: 日期选择器默认值无效:使用代码跟 ...
 - -webkit-overflow-scrolling:touch介绍和碰到的坑
			
1.作用 可控制元素在移动设备有滚动回弹效果,可惯性滚动 2.适应场景 在ios移动端上,设置容器overflow-y:scroll;使容器内元素滚动时,滑动会很卡顿,使用-webkit-overfl ...