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

目录
相关文章
|
6天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
25 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
8天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
27 10
|
6天前
|
API Android开发 iOS开发
安卓与iOS开发中的线程管理对比
【9月更文挑战第12天】在移动应用的世界中,安卓和iOS平台各自拥有庞大的用户群体。开发者们在这两个平台上构建应用时,线程管理是他们必须面对的关键挑战之一。本文将深入探讨两大平台在线程管理方面的异同,通过直观的代码示例,揭示它们各自的设计理念和实现方式,帮助读者更好地理解如何在安卓与iOS开发中高效地处理多线程任务。
|
8天前
|
Java Android开发 开发者
安卓应用开发中的线程管理优化技巧
【9月更文挑战第10天】在安卓开发的海洋里,线程管理犹如航行的风帆,掌握好它,能让应用乘风破浪,反之则可能遭遇性能的暗礁。本文将通过浅显易懂的语言和生动的比喻,带你探索如何优雅地处理安卓中的线程问题,从基础的线程创建到高级的线程池运用,让你的应用运行更加流畅。
|
15天前
|
存储 Ubuntu Linux
C语言 多线程编程(1) 初识线程和条件变量
本文档详细介绍了多线程的概念、相关命令及线程的操作方法。首先解释了线程的定义及其与进程的关系,接着对比了线程与进程的区别。随后介绍了如何在 Linux 系统中使用 `pidstat`、`top` 和 `ps` 命令查看线程信息。文档还探讨了多进程和多线程模式各自的优缺点及适用场景,并详细讲解了如何使用 POSIX 线程库创建、退出、等待和取消线程。此外,还介绍了线程分离的概念和方法,并提供了多个示例代码帮助理解。最后,深入探讨了线程间的通讯机制、互斥锁和条件变量的使用,通过具体示例展示了如何实现生产者与消费者的同步模型。
|
20天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享安卓与iOS开发中的线程管理比较
【8月更文挑战第30天】本文将探讨网络安全与信息安全的重要性,并分享关于网络安全漏洞、加密技术和安全意识的知识。我们将了解常见的网络攻击类型和防御策略,以及如何通过加密技术和提高安全意识来保护个人和组织的信息安全。
|
Java Android开发 调度
|
4天前
|
Android开发 开发者 Kotlin
探索安卓开发中的新特性
【9月更文挑战第14天】本文将引导你深入理解安卓开发领域的一些最新特性,并为你提供实用的代码示例。无论你是初学者还是经验丰富的开发者,这篇文章都会给你带来新的启示和灵感。让我们一起探索吧!