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也是顺序执行后台任务的。

欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!
AntDream

目录
相关文章
|
12天前
|
Java 数据库 Android开发
【专栏】构建高效 Android 应用:探究 Kotlin 多线程优化策略
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
|
21小时前
|
Java
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
6 1
|
21小时前
|
Java 调度
【Java多线程】线程中几个常见的属性以及状态
【Java多线程】线程中几个常见的属性以及状态
5 0
|
22小时前
|
Java 调度
【Java多线程】对进程与线程的理解
【Java多线程】对进程与线程的理解
9 1
|
2天前
|
存储 安全 Java
【探索Linux】P.21(多线程 | 线程同步 | 条件变量 | 线程安全)
【探索Linux】P.21(多线程 | 线程同步 | 条件变量 | 线程安全)
9 0
|
2天前
|
算法 安全 Linux
【探索Linux】P.20(多线程 | 线程互斥 | 互斥锁 | 死锁 | 资源饥饿)
【探索Linux】P.20(多线程 | 线程互斥 | 互斥锁 | 死锁 | 资源饥饿)
9 0
|
2天前
|
存储 安全 Linux
【探索Linux】P.19(多线程 | 线程的概念 | 线程控制 | 分离线程)
【探索Linux】P.19(多线程 | 线程的概念 | 线程控制 | 分离线程)
6 0
|
10天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
10天前
|
缓存 安全 Java
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
|
10天前
|
数据采集 安全 Java
Python的多线程,守护线程,线程安全
Python的多线程,守护线程,线程安全

热门文章

最新文章