Android多线程-HandlerThread用法与源码解析

本文深入解析了Android中的HandlerThread类,探讨了其在多线程通讯中的应用,通过源码分析展示了HandlerThread的工作原理,并提供了使用示例。

使用HandlerThread好处

在Android开发中,我们经常使用多线程编程。而多线程有多种方式实现。其中我们用得最多、也是最早接触的是使直接开一个线程Thread

new Thread(){
    @Override
    public void run() {
        //do something here
    }
}.start();

先抛开这样开线程的弊端,因为在有时做一些简单的任务时,这样写确实能减少代码量;我们先说说线程间通讯。Android自带提供HandlerLooper的组合来实现。使用方法相信大家都很熟悉了。而HandlerThread就是为了实现多线程之间通讯的一个类,可以减少一定的代码量。

HandlerThread源码解析

首先,我们先看看源码(不感兴趣可以跳过,下方有使用方法解析):

package android.os;

/**
 * Handy class for starting a new thread that has a looper. The looper can then be 
 * used to create handler classes. Note that start() must still be called.
 * 
 * 这是一个方便启动一个带有`Looper`的`Thread`,然而`start()`还是需要被调用
 *
 */
public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     *
     * 输入的优先级是来自`android.os.Process`里的,而不是来自`java.lang.Thread`里的
     *
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

这是HandlerThread类的开头,我们可以看到,这个类属于android.os包,属于sdk内的类,使用方便,无需另外导入。
该类继承于Thread类,本质上是一个线程。
该类提供两个构造方法,单参数构造方法,输入参数为线程名字,双参数构造方法输入线程名字以及线程优先级,这里需要注意一点,输入的优先级是android.os.Process里的,而不是java.lang.Thread里的。

我们再往下看代码:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

这是核心部分,当线程被启动后,调用该run()方法。首先,记录了该线程的id号,然后调用Looper.prepare(),创建该线程上的looper对象。
接着对自身对象加锁,并获取该线程上的looper引用,并调用notifyAll(),唤醒其他正在等待该对象的线程。做这一步的原因,我们后面再做解释。
然后在进程里对当前线程设置优先级。
最后调用Looper.loop(),启动looper的消息队列循环。
到此,该类以及基本可以运行了

我们再往下看代码:

/**
 * This method returns the Looper associated with this thread. If this thread not been started
 * or for any reason is isAlive() returns false, this method will return null. If this thread 
 * has been started, this method will block until the looper has been initialized. 
 * 
 * 该方法会返回一个关联该线程的Looper
 * 如果该线程还未启动,或者某种原因isAlive返回false,这个方法会会返回null值
 * 如果线程已经启动,这个方法会阻塞,直到looper被初始化
 * 
 * @return The looper.
 */
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;
}

从注释中,我们可以看到,该方法是返回一个和该类线程相关的looper,首先判断该线程是否正在运行,若否,则返回一个空值(线程未启动,当然没有关联的looper)。
接着对自身对象加锁,再次判断线程是否正在运行,且mLooper是否已经赋值。这里用到的方法是双重检测,和单例模式中的双重检测是一样的。若线程已经在运行,但mLooper未赋值,那就在该线程等待。
我们可以和上面的run方法联系起来了。直到run()方法执行到notifyALL(),才被唤醒,继续判断,直到mLooper赋值,返回mLooper
这样写的目的是为了防止多线程操作下,防止某个线程从一个已经运行的HandlerThread但还未完成run方法的对象里,获取到空的looper引用。

HandlerThread用法

那么我们平时怎么使用HandlerThread这个类呢?
首先我们可以创建一个HandlerThread类实例,并运行该线程,那么该线程就开始进入等待消息的状态:

handlerThread = new HandlerThread("myHandlerThread");
handlerThread.start();

接着我们可以创建一个和该线程的Handler,里面实现我们业务需求的执行的方法,构造方法里就可以传入我们HandlerThread类实例的looper,这样,handler就和我们的线程关联在一起了:

handler =new Handler(handlerThread.getLooper()){
    @Override
    public void handleMessage(Message msg) {
        //这里可以实现我们的业务需求
        Log.i(TAG,"receive msg:"+msg.what);
    }
};

接下来,就和我们平时使用handler一样使用了,该任务就会在HandlerThread实例的线程运行了:

handler.sendEmptyMessage(123);
下载前可以先看下教程 https://pan.quark.cn/s/16a53f4bd595 小天才电话手表刷机教程 — 基础篇 我们将为您简单的介绍小天才电话手表新机型的简单刷机以及玩法,如adb工具的使用,magisk的刷入等等。 我们会确保您看完此教程后能够对Android系统有一个最基本的认识,以及能够成功通过magisk root您的手表,并安装您需要的第三方软件。 ADB Android Debug Bridge,简称,在android developer的adb文档中是这么描述它的: 是一种多功能命令行工具,可让您设备进行通信。 该命令有助于各种设备操作,例如安装和调试应用程序。 提供对 Unix shell 的访问,您可以使用它在设备上运行各种命令。 它是一个客户端-服务器程序。 这听起来有些难以理解,因为您也没有必要去理解它,如果您对本文中的任何关键名词产生疑惑或兴趣,您都可以在搜索引擎中去搜索它,当然,我们会对其进行简单的解释:是一款在命令行中运行的,用于对Android设备进行调试的工具,并拥有比一般用户以及程序更高的权限,所以,我们可以使用它对Android设备进行最基本的调试操作。 而在小天才电话手表上启用它,您只需要这么做: - 打开拨号盘; - 输入; - 点按打开adb调试选项。 其次是电脑上的Android SDK Platform-Tools的安装,此工具是 Android SDK 的组件。 它包括 Android 平台交互的工具,主要由和构成,如果您接触过Android开发,必然会使用到它,因为它包含在Android Studio等IDE中,当然,您可以独立下载,在下方选择对应的版本即可: - Download SDK Platform...
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值