Android多线程之常见的线程形态
Android 多线程系列
Andorid中的线程除了传统的Thread外,主要还有AsyncTask、HandlerThread、IntentService。
AsyncTask
AsyncTask是一种轻量的异步任务类,不仅可以在后台执行任务,还能把执行的进度和最终的结果传递给UI线程以便更新UI。AsyncTask底层是封装了Thread和Handler。AsyncTask不适合执行特别耗时的任务,这种情况下还是推荐用线程池来处理
-
几个核心方法
- onPreExecute:在主线程中执行,在异步任务执行之前执行,可以做一些准备工作
- doInBackground:在线程池中执行,执行具体的异步任务。在这个方法中可以调用publishProgress方法来更新任务的进度
- onProgressUpdate:在主线程中执行,调用publishProgress方法后会被调用
- onPostExecute:在主线程中执行,异步任务执行完毕后会被调用,返回执行结果
- onCancelled:在主线程中执行,异步任务被取消时会被调用,这样onPostExecute方法将不会被调用
- AsyncTask必须在主线程中加载,这意味着第一次访问AsyncTask必须发生在主线程。Android4.1及以上的版本中已经在ActivityThread的main方法中自动完成了
- AsyncTask对象必须在主线程中创建
- AsyncTask的execute方法必须在UI线程调用
- 不要在程序中直接调用onPreExecute、doInBackground、onProgressUpdate、onPostExecute方法
- 一个AsyncTask对象只能执行一次,只能调用一次execute方法,否则会报IllegalStateException异常
- 默认情况下AsyncTask是串行执行的
HandlerThread
- HandlerThread继承自Thread
public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; //构造方法需要传入线程的名字 public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } public HandlerThread(String name, int priority) { super(name); mPriority = priority; } //用来重写,在开启消息循环之前被调用 protected void onLooperPrepared() { } //主要的地方在这个run方法 @Override public void run() { mTid = Process.myTid(); //创建消息队列 Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); //开启消息循环 Looper.loop(); mTid = -1; } public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } //用于停止消息循环 public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } //用于停止消息循环 public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; } public int getThreadId() { return mTid; }
- HandlerThread与普通的Thread不同的地方在于它在run方法中开启了消息循环,外界需要通过Handler的消息的方式来通知HandlerThread执行一个具体的任务
- 由于HandlerThread的run方法是一个无限循环,因此当不需要再使用HandlerThread时,可以通过quit和quitSafely方法来终止线程的执行
IntentService
- IntentService 是一个抽象类,所以必须创建它的子类才能使用IntentService
- IntentService继承自Service,因此是一种特殊的服务,优先级比普通的后台线程要高,不容易被回收,适合执行一些高优先级的后台任务
- IntentService封装了HandlerThread和Handler
public abstract class IntentService extends Service { private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery; //自定义的Handler,这样可以把收到的任务消息发送给HandlerThread处理 private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { //onHandleIntent处理具体的任务,运行在HandlerThread中 onHandleIntent((Intent)msg.obj); //任务执行完毕会自动结束 stopSelf(msg.arg1); } } public IntentService(String name) { super(); mName = name; } public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } //第一次启动时会调用onCreate @Override public void onCreate() { super.onCreate(); //创建HandlerThread HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); //调用HandlerThread的run方法,开启HandlerThread的消息循环,以便接收消息处理具体的任务 thread.start(); //获取HandlerThread的looper,创建ServiceHandler,这样通过ServiceHandler发送的消息最后都会在HandlerThread中处理 mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { //每次调用IntentService都会执行onStartCommand方法,发送一个任务消息给HandlerThread处理,任务的信息通过Intent传递 onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { mServiceLooper.quit(); } @Override @Nullable public IBinder onBind(Intent intent) { return null; } @WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent); }
- IntentService通过Intent来传递任务参数,当任务执行完毕时会调用stopSelf(int startId)自己停止服务
- IntentService的onHandleIntent是一个抽象方法,需要我们自己实现,用于处理具体的任务。
- 每执行一个后台任务就需要启动一次IntentService,IntentService内部通过消息的方式向HanderThread请求执行任务,Handler的Looper是顺序执行任务的,所以IntentService也是顺序执行后台任务的。
欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Safari上使用WebRTC指南
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/82948390 尽管Apple在2017年的WWDC上宣布加入WebRTC支持,但仍然没有看到Apple在支持WebRTC上更深入的举动,尤其是其不只支持VP8更加强了这种担忧。 文 / Chad Phillips 译 / 元宝 原文:https://webrtchacks.com/guide-to-safari-webrtc/ 自Apple首次向Safari添加WebRTC支持以来,已有一年多的时间了。鉴于WebRTC的差异和局限性,如何最好地开发Safari的WebRTC应用程序仍然存在许多问题。Chad是长期开源人员,也是FreeSWITCH产品的贡献者。他自2015年以来一直参与WebRTC的开发工作。他最近推出了MoxieMeet,一个在线体验活动的视频会议平台,在那里他担任首席技术官,并为这篇文章将展示他许多见解。 Safari和WebRTC在野外。由Flickr用户Curious Expedition...
- 下一篇
iOS 常用关键字 static、const、 extern、define
const 常量: 共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以被修改,在编译阶段会执行类型检查. 全局常量 包括在 .h .m 文件除非 ****@implementation**** 作用域内声明的, 都属于全局常量, 都可能由外部进行访问。 外部文件访问时需要 使用关键字 ****extern**** 并且指明常量声明的类型来使用, 否则编译器默认以 int 类型来处理。应该是与运行时有关。 局部常量 在 .m ****@implementation**** 内 方法实现内进行声明, 只作用于 主要用于修饰 C 或 OC 数据类型, 使声明的变量定义为常量。 三种修饰写法不同作用. const NSString * name = @"Jersey"; 使 *name 指针地址不可变, 实际指向内容不受影响, 修改指针地址编译器报错。 NSString const * name = @"Jersey"; 同上面写法一致. NSString * const name = @"Jersey"; 使 *name 指针指向内容不可变, 指针地址不受影响, 修改内容则编...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Mario游戏-低调大师作品
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装