实例分析Android中HandlerThread线程用法

一、HandlerThread的介绍及使用举例     

HandlerThread是什么鬼?其本质就是一个线程,但是HandlerThread在启动的时候会帮我们准备好一个Looper,并供外界使用,说白了就是使我们在子线程中更方便的使用Handler,比如没有HandlerThread我们要在子线程使用Handler,写法如下:

private Handler mHandler;    @Override     public void run() {        super.run();         Looper.prepare();         mHandler = new Handler(){             @Override             public void handleMessage(Message msg) {             }         };         Looper.loop();}

有了HandlerThread就不用我们自己管理Looper了,至于为什么分析源码的时候就明白了。

HandlerThread使用简单介绍:

首先我们要初始化HandlerThread然后调用其start方法,也就是开启线程:

mHandlerThread = new HandlerThread("mHandlerThread");//这里的mHandlerThread其实就是线程的名字
mHandlerThread.start();

接下来初始化一个Handler并且将mHandlerThread中的Looper作为构造函数参数传递给Handler:

mHandler = new Handler(mHandlerThread.getLooper())

这样就保证了Hnadler运行在子线程。并且需要在适合的时机调用HandlerThread的quit方法或quitSafely方法,如Activity销毁的时候:

@Override
protected void onDestroy() {
   //
   super.onDestroy();
   //释放资源
   mHandlerThread.quit();
}

quit()与quitSafely()方法比较(这里只说一些结论,源码可以自己查看):

相同点:

调用之后MessageQueue消息队列均不在接受新的消息加入队列。

不同点:

quit方法把MessageQueue消息池中所有的消息全部清空。quitSafely方法只会清空MessageQueue消息池中所有的延迟消息(延迟消息是指通过sendMessageDelayed或postDelayed等方法发送的消息),非延迟消息则不清除继续派发出去让Handler去处理。

接下来我们完整看一下HandlerThread例子源码:

 public class MainActivity extends Activity {     private HandlerThread mHandlerThread;     private Handler mHandler;     private boolean flag;     //     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);        mHandlerThread = new HandlerThread("mHandlerThread");         mHandlerThread.start();         mHandler = new Handler(mHandlerThread.getLooper()) {             @Override             public void handleMessage(Message msg) {                 //                 try {                     Thread.sleep(2000);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                 if(flag){                     Log.i("HandlerThread", "更新:"+new Random().nextInt(1000));                 }                 mHandler.sendEmptyMessage(1);             }         };     }     @Override     protected void onResume() {         //         super.onResume();         flag = true;         mHandler.sendEmptyMessage(1);     }     @Override     protected void onPause() {         //         super.onPause();         flag = false;     }     @Override     protected void onDestroy() {         //         super.onDestroy();         //释放资源         mHandlerThread.quit();     }}

运行程序就会在控制台看到每隔两秒有Log打出。至于HandlerThrea的使用就到此为止了,看懂上面小例子就差不多了。

二、HandlerThread的源码分析

HandlerThread源码非常简短,出去注释不到100行,这里就直接全部贴出来了:

 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.      */    public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;     }    /**      * Call back method that can be explicitly overridden if needed to execute some      * setup before Looper loops.     */     protected void onLooperPrepared() {     }    @Override    public void run() {         mTid = Process.myTid();         Looper.prepare();         synchronized (this) {            mLooper = Looper.myLooper();             notifyAll();         }        Process.setThreadPriority(mPriority);        onLooperPrepared();         Looper.loop();         mTid = -1;     }     /**      * 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.        * @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;     }     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;     }     /**      * Returns the identifier of this thread. See Process.myTid().      */     public int getThreadId() {         return mTid;     } }

看第一行就知道了其本质就是一个线程。

6-9行以及17-20行构造函数,也很简单,就是初始化的时候我们可以定义线程名字,还可以传入线程优先级。

初始化完成,紧接着调用start()开发线程就会执行run方法逻辑。

30-41行代码,最重要的就是调用Looper.prepare()以及Looper.loop()方法为我们在子线程准备好一个Looper。并且用变量mLooper记录,调用getLooper()方法的时候返回。

但是,细心的你肯定发现run()方法中有个notifyAll(),getLooper()中有个wait()为什么要加这些鸟玩意?

大家发现没在HandlerThread 例子中Handler的创建是在主线程完成的,创建的时候需要调用HandlerThread的getLooper()获取mLooper作为参数传递给Handler的构造函数,而Looper的创建是在子线程中创建的,这里就有线程同步问题了,比如我们调用getLooper()的时候HandlerThread中run()方法还没执行完,mLooper变量还未赋值,此时就执行了wait()等待逻辑,一直等到run()方法中mLooper被赋值,之后立即执行notifyAll(),然后getLooper()就可以正确返回mLooper了。

明白了吧,不明的话这里需要花些时间好好理解下,好了源码主要部分就分析完了,看到这里相信你对HandlerThread有了一定的了解了。

HandlerThread 还是比较简单理解的,好了,本篇到此为止,希望对你有帮助。

(0)

相关推荐

  • Android实例HandlerThread源码分析

    HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我又有一 个耗时任务需要执行,我们不得不重新创建线程去执行该耗时任务.然而,这样就存在一个性能问题:多次创建和销毁线程是很耗 系统资源的.为了解这种问题,我们可以自己构建一个循环线程Looper Thread,当有耗时任务投放到该循环线程中时,线程执行耗 时任务,执行完之后循环线程处于等待状态,直到下一个新的耗时任务被投放进来.这样一来就避免了多次

  • Android HandlerThread的使用及原理详解

    一.HandlerThread的含义 HandlerThread能够新建拥有Looper的线程.这个Looper能够用来新建其他的Handler.(线程中的Looper)需要注意的是,新建的时候需要被回调. 二.HandlerThread的用法 一般情况下,我们会经常用Handler在子线程中更新UI线程,那是因为在主线程中有Looper循环,而HandlerThread新建拥有Looper的子线程又有什么用呢? 必然是执行耗时操作.举个例子,数据实时更新,我们每10秒需要切换一下显示的数据,如

  • Android用HandlerThread模拟AsyncTask功能(ThreadTask)

    前言 AsyncTask是个好东西,能处理绝大多数应用线程和更新UI的任务,由于其内部使用了静态线程池,如果你有一堆异步任务(例如全局定时更新数据.同一个Activity中多个AsyncTask同时执行)其中有不能马上执行完的情况(例如网络请求超时),那就糟了,其他任务都还等着呢,就会出现任务卡住的情况.此时就需要直接上Thread了,这里参考AsyncTask的API封装了一个ThreadTask,便于必要时代码替换,欢迎交流!  正文实例代码: import android.os.Handl

  • Android HandlerThread使用方法详解

    Android HandlerThread使用方法详解 HandlerThread 继承自Thread,内部封装了Looper. 首先Handler和HandlerThread的主要区别是:Handler与Activity在同一个线程中,HandlerThread与Activity不在同一个线程,而是别外新的线程中(Handler中不能做耗时的操作). 用法: import android.app.Activity; import android.os.Bundle; import androi

  • android使用handlerthread创建线程示例

    在android开发中,一说起线程的使用,很多人马上想到new Thread(){...}.start()这种方式.这样使用当然可以,但是多次使用这种方式,会创建多个匿名线程.使得程序运行起来越来越慢.因此,可以考虑使用一个Handler来启动一个线程,当该线程不再使用就删除,保证线程不会重复创建.一般会使用Handler handler = new Handler(){...}创建Handler.这样创建的handler是在主线程即UI线程下的Handler,即这个Handler是与UI线程下

  • 实例分析Android中HandlerThread线程用法

    一.HandlerThread的介绍及使用举例      HandlerThread是什么鬼?其本质就是一个线程,但是HandlerThread在启动的时候会帮我们准备好一个Looper,并供外界使用,说白了就是使我们在子线程中更方便的使用Handler,比如没有HandlerThread我们要在子线程使用Handler,写法如下: private Handler mHandler;    @Override     public void run() {        super.run();

  • 代码实例分析android中inline hook

    以下内容通过1.实现目标注入程序,2.实现主程序,3.实现注入函数,4.thumb指令集实现等4个方面详细分析了android中inline hook的用法,以下是全部内容: 最近终于沉下心来对着书把hook跟注入方面的代码敲了一遍,打算写几个博客把它们记录下来. 第一次介绍一下我感觉难度最大的inline hook,实现代码参考了腾讯GAD的游戏安全入门. inline hook的大致流程如下: 首先将目标指令替换为跳转指令,跳转地址为一段我们自己编写的汇编代码,这段汇编代码先是执行用户指定的

  • Android中BaseAdapter的用法分析与理解

    本文实例分析了Android中BaseAdapter的用法.分享给大家供大家参考,具体如下: 最近做一个项目,项目中用到了ListView,ListView最重要的就是绑定数据,这个数据由Adapter来提供,这里我重写了BaseAdapter这个类来实现自己的menuAdapter代码如下: package org.leepood.lanorder; import java.io.InputStream; import java.util.ArrayList; import java.util

  • 分析Android中线程和线程池

    目录 前言 HandlerThread IntentService 线程池的好处 ThreadPoolExecutor 线程池的分类 FixedThreadPool CachedThreadPool ScheduledThreadPool SingleThreadExecutor 前言 由于内容过多,所以将分为上下两部分,第一部分主要和大家谈谈Android中的线程,以及在Android中的常用的线程池.第二部分我们一起来了解一下AsyncTask的使用和工作原理. HandlerThread

  • Android中AlarmManager基本用法分析

    本文实例讲述了Android中AlarmManager基本用法.分享给大家供大家参考,具体如下: AlarmManager的作用文档中的解释是:在特定的时刻为我们广播一个指定的Intent.简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent. 对应AlarmManager更深层的了解可以参考: http://www.jb51.net/article/90491.htm android提供了四种类型的闹钟: ① ELAPSED_REALT

  • Android中ExpandableListView的用法实例

    本文实例讲述了Android中ExpandableListView的用法,ExpandableListView是android中可以实现下拉list的一个控件,具体的实现方法如下: 首先:在layout的xml文件中定义一个ExpandableListView 复制代码 代码如下: <LinearLayout       android:id="@+id/linearLayout"      android:layout_width="fill_parent"

  • Android中persistent属性用法详解

    本文实例讲述了Android中persistent属性用法.分享给大家供大家参考,具体如下: 前段时间在研究telephony时,一直没有在framework下发现对telephony的初始化(PhoneFactory.Java中的makeDefaultPhones函数)的调用.结果全局搜索之后发现在application PhoneApp(packages/apps/Phone)中调用了.但是application PhoneApp既没有被Broadcast唤醒,也没有被其他service调用

  • 分析Android中应用的启动流程

    前言 在我们开始之前,希望您能最好已经满足以下条件: 1.有一份编译后的Android源码(亲自动手实践才会有更深入的理解) 2.对Binder机制有一定的了解 本文启动流程分析基于Android 5.1的源码.为什么是5.1的源码呢?因为手边编译完的代码只有这个版本-另外,用什么版本的源码并不重要,大体的流程并无本质上的区别,仅仅是实现细节的调整,找一个你熟悉的版本就好. 1.启动时序图 作为一个轻微强迫症的人,整理的时序图,相信大家按图索骥,一定能搞明白整个启动流程: 说明:为了让大家更清楚

  • Android中Intent习惯用法

    Android中的Intent是一个非常重要的类,如果对Intent不是特别了解,可以参见<详解Android中Intent的使用方法>.如果对Intent Filter不是特别了解,可以参见<详解Android中Intent对象与Intent Filter过滤匹配过程>. 本文着重讲一下Android中一些常见的Intent的习惯用法,比如如何通过Intent发送短信.发送邮件.启动摄像机拍照录视频.设置闹铃.打开WIFI设置界面等等. 限于篇幅,本文分为上下两篇,这是上篇. 发

  • 实例分析javascript中的异步

    js 异步解析 一 .js单线程分析 我们都知道js的一大特点是单线程,也就是同一时间点,只能处理一件事,一句js代码.那为什么js要设计成单线程而不是多线程呢?这主要和js的用途有关,js作为浏览器端的脚本语言,主要的用途为用户与服务端的交互与操作dom.而操作dom就注定了js只能是单线程语言.假如js才取多线程将会出现,多个线程同时对一个dom进行操作的情况,浏览器将无法判断如何渲染.不仅js是单线程,浏览器渲染dom也是单线程的,js的执行和浏览器渲染dom共用的一个线程,这就导致了在h

随机推荐