Android ——对HandlerThread的理解和注意事项

源码分析

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() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        //prepare()方法中创建了一个Looper对象,并且把该对象放到了该线程范围内的变量中(sThreadLocal),在Looper对象的构造过程中,初始化了一个MessageQueue,作为该Looper对象成员变量。
        Looper.prepare();// 为子线程创建Looper 和 MessageQueue

        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();// 通知getLooper()方法Looper创建好了
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();//开启Looper,不断的循环从MessageQueue中取消息处理了,当没有消息的时候会阻塞,有消息的到来的时候会唤醒
        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();// 等待run()方法中Looper创建完成
                } 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;
    }
}

用法

1、创建一个HandlerThread,即创建了一个包含Looper的线程。

HandlerThread handlerThread = new HandlerThread("test");
handlerThread.start(); // 开启线程

2、获取HandlerThread的Looper。

Looper looper = handlerThread.getLooper();

3、创建Handler,通过Looper初始化。

Handler handler = new Handler(looper);

现在我们通过handler发送消息,就会在子线程中执行。

用完后一定要记得退出HandlerThread。

handlerThread.quit();

和普通Thread的不同

1、区别

HandlerThread继承自Thread,调用start()实际上是调用了底层run方法,同时创建了一个含有消息队列的Looper,并对外暴露接口(getLooper()),提供自己这个Looper对象,Looper.loop()方法默认是死循环,线程运行完成或程序退出需要手动关闭这个Looper,这就是它和普通Thread的不同。

2、优势

1、我们平常在开发中经常使用new Thread(){}.start()这种方式开启一个子线程,这会创建多个匿名线程,占用系统资源,而HandlerThread自带Looper使他可以通过消息队列来重复使用当前线程,节省系统资源开销。这是它的优点也是缺点,每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。

2、android系统提供的Handler类内部的Looper默认绑定的是UI线程的消息队列,对于非UI线程又想使用消息机制,只能自定义一个线程,在线程run()方法中,通过 Looper.prepare();Looper.loop();来开启Looper和消息队列,其实就是Google攻城狮给我实现好的HandlerThread,HandlerThread绑定的是它自己的消息队列,它不会干扰或阻塞UI线程。IntentService内置的是HandlerThread作为异步线程。

注意事项

一旦我们使用了HandlerThread,需要特别注意给HandlerThread设置不同的线程优先级,CPU会根据设置的不同线程优先级对所有的线程进行调度优化。

适用场景

因为HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程,比较合适处理那些需要花费时间偏长的任务。我们只需要把任务发送给HandlerThread,然后就只需要等待任务执行结束的时候通知返回到主线程就好了。

时间: 2024-10-27 00:11:44

Android ——对HandlerThread的理解和注意事项的相关文章

关于Android应用开发的一些安全注意事项

原文地址: http://www.javacodegeeks.com/2014/05/simple-tips-to-secure-android-app.html http://developer.android.com/training/articles/security-tips.html Android已经具有内置到操作系统的安全功能,显著降低应用安全问题的频次和影响,但作为应用程序开发人员,我们也需要注意在开发应用程序时的安全问题. 安全级别是取决于应用程序的类型和域. 这里有我们需要注

Android 3D emulation 架构理解

Android Emulator 给用户提供  GPU on 选项,意思是利用 Host ( 就是执行 Emulator 的PC机) 的 GPU. 当然PC机必须把 OpenGL 的驱动装好 在实现上就是把 libGLESv1_CM.so  libGLESv2.so 替换掉,当system调用 gl的函数的时候,把调用打包为stream,并通过 pipe 发送到 host端处理,进入转化为对 host opengl的调用. 光这样还不够,还要把 libegl, libgralloc 都替换了,由

百度Android语音识别SDK语义理解与解析方法

百度语义理解开放平台面向互联网开发者提供自然语言文本的解析服务,也就是可以根据文本的意图解析成相应的表示. 为了易于人阅读,同时也方便机器解析和生成,意图表示协议采用 json 语言进行描述,采用 gb18030 编码. json 语言的基本概念: 1.属性名/属性值 即键值对(key-value) 2.数组 在 json 中是"[]"括起来的内容,数据结构为 ["value1","value2",...],取值方式和所有语言中一样,使用索引获取

Android Dalvikvm 内存管理理解

网上很多文件介绍了 jvm 内存管理的理论,但在 Dalvikvm 中,究竟是如何实现的. 这几天猛看了 Dalvikvm 的源代码,说一下我的理解: 在大层面上讲跟理论一样,jvm 把内存分成了一些区, 关于各区的说明参见. http://blog.csdn.net/lengyuhong/article/details/5953544 对于hello world 这样简单程序,发现dalvikvm也就用了一个heap, 就是Eden区了. dalvikvm 使用 mmap 创建共享内存(堆是多

Android培训HandlerThread的使用及源码解析

Android培训HandlerThread的使用及源码解析-北京尚学堂 关于Hanlder的基本使用可以参见博文<Android中Handler的使用>,如果想了解Handler.Looper.Thread等的相互关系以及内部实现原理可以参见博文<深入源码解析Android中的Handler,Message,MessageQueue,Looper>. Android中的API中对HandlerThread的描述是: Handy class for starting a new t

Android菜单详解——理解android中的Menu

Android菜单详解--理解android中的Menu 前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至今为止看到的最好的一本android书,中文版出到<精通Android 2>. 理解Android的菜单 菜单是许多应用程序不可或缺的一部分,Android中更是如此,所有搭载Android系统的手机甚至都要有一个"Menu&qu

android handler HandlerThread 用法

一.Handler Handler在android里负责发送和处理消息.它的主要用途有: 1)按计划发送消息或执行某个Runnanble(使用POST方法): 2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程) 默认情况下,Handler接受的是当前线程下的消息循环实例(使用Handler(Looper looper).Handler(Looper  looper, Handler.Callback callback) 可以指定线程),同时一个消息队列可以被当前线程中

Android 4.4 中 WebView 使用注意事项

Android 4.4 中 WebView 使用注意事项 自Android 4.4起,Android中的WebView开始基于Chromium( 这大概是因为Android部门负责人从Andy Rubin变成了Chrome部门的主管Sundar Pichai了吧,_). 这个改变,使得WebView的性能大幅度提升,并且对HTML5, CSS3, and JavaScript有了更好的支持. 那么,作为一个客户端开发者,我们写代码的时候需要注意哪些呢? 1.多线程 如果你在子线程中调用WebVi

android 反编译 混淆过程中注意事项

此文源自组内成员分享的PPT,其他成员的文档由于没有得到授权,暂不公开. 本文命令如果没有特殊注明,均为windows 7环境. 本文只涉及大概的知识点,不涉及具体的细节,需要注意. 反编译 apktool 可反编译资源文件(xml,点九图)以及代码为smali代码 使用命令:apktool d xxx.apk output_filepath dex2jar 反编译dex文件(解压apk获得的classes.dex)为jar 使用命令:dex2jar xxx.dex jd-gui 查看jar文件