HandlerThread总结

本文介绍了Android中用于处理耗时任务的HandlerThread,包括如何创建实例、启动线程、构建消息处理机制以及退出线程的正确方式。同时,深入解析了HandlerThread的构造方法、run()、getLooper()、quit()和quitSafe()方法的工作原理,帮助理解其内部的线程同步和资源管理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Android系统中,执行耗时操作必须使用子线程来执行,执行完线程以后线程便会自动销毁。但是如果如果我们有很多分步的耗时操作,如果我们不断的创建新的线程执行,不断销毁线程便会消耗很多的性能,那么该怎么办呢?android给我们提供了两个方法,一个就是使用本篇文章讲的HandlerThread,另一个便是使用线程池管理线程。

一、简单使用

1.创建实例对象

//参数表示线程名称
HandlerThread handlerThread = new HandlerThread("myHandlerThread");

2.启动HandlerThread线程

handlerThread.start();

3.构建循环消息处理机制

mThreadHandler = new Handler(mHandlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        //耗时操作
    }
};

4.退出循环

如果不需要处理耗时的任务了需要让looper停下来,回收资源

mHandlerThread.getLooper().quit()
或者
mHandlerThread.getLooper().quitSafely()

二、源码解析

1.构造方法

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

public HandlerThread(String name, int priority) {
    super(name);
    mPriority = priority;
}

传入的字符串参数为线程的名字,整形参数为线程优先级,如果不指定线程优先级会被设定为默认的优先级

2.run()方法和getLooper()方法

public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    //持有锁机制来获得当前线程的Looper对象
    synchronized (this) {
        mLooper = Looper.myLooper();
        //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait
        notifyAll();
    }
    //设置线程的优先级别
    Process.setThreadPriority(mPriority);
    //这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前的准备,方便扩展
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}
public Looper getLooper() {
    if (!isAlive()) {
        return null;
    }
    // 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功,阻塞
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

使用HandlerThread的时候必须调用start()方法,因为调用start()之后,线程会交由虚拟机进行调度,虚拟机会调用run方法,完成looper的初始化,在这里还用到了锁,是为了保证线程同步,在looper实例化完成之后才获取它的对象。

3.quit()方法和quitSafe()方法

//调用这个方法退出Looper消息循环,及退出线程
public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quit();
        return true;
    }
    return false;
}
//调用这个方法安全地退出线程
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean quitSafely() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quitSafely();
        return true;
    }
    return false;
}

这两个方法最后都会调用looper对象对应的方法

void quit(boolean safe) {
    if (!mQuitAllowed) {
        throw new IllegalStateException("Main thread not allowed to quit.");
    }
    synchronized (this) {
        if (mQuitting) {
            return;
        }
        mQuitting = true;
        //安全退出调用这个方法
        if (safe) {
            removeAllFutureMessagesLocked();
        } else {//不安全退出调用这个方法
            removeAllMessagesLocked();
        }
        // We can assume mPtr != 0 because mQuitting was previously false.
        nativeWake(mPtr);
    }
}

removeAllMessagesLocked()

private void removeAllMessagesLocked() {
    Message p = mMessages;
    while (p != null) {
        Message n = p.next;
        p.recycleUnchecked();
        p = n;
    }
    mMessages = null;
}

非安全退出会遍历Message链表,回收所有消息

removeAllFutureMessagesLocked()

private void removeAllFutureMessagesLocked() {
    final long now = SystemClock.uptimeMillis();
    Message p = mMessages;
    if (p != null) {
        //判断当前队列中的消息是否正在处理这个消息,没有的话,直接移除所有回调
        if (p.when > now) {
            removeAllMessagesLocked();
        } else {//正在处理的话,等待该消息处理处理完毕再退出该循环
            Message n;
            for (;;) {
                n = p.next;
                if (n == null) {
                    return;
                }
                if (n.when > now) {
                    break;
                }
                p = n;
            }
            p.next = null;
            do {
                p = n;
                n = p.next;
                p.recycleUnchecked();
            } while (n != null);
        }
    }
}

安全退出会根据Message.when这个属性,判断我们当前消息队列是否正在处理消息,没有正在处理消息的话,直接移除所有回调,正在处理的话,等待该消息处理处理完毕再退出该循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幽蓝丶流月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值