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条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS关闭SELinux安全模块