为什么要用HandlerThread,怎么用?

原文链接:http://i.she.vc/yuanchuang/144470.html


  • 作为一个Android开发,Handler机制是一定要了解的。在我面试过程中,发现很多人对Handler和Looper机制非常了解,对答如流,但是却不知道何为HandlerThread。本文我们就来简单聊一下它

    HandlerThread是Thread的子类,它的作用很明确,文档说的也很清楚

    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.

    意思就是说HandlerThread帮我们创建好了Looper。我们都知道,Android主线程的Looper是自动创建的,其他线程是没有创建Looper的,需要我们自己创建。一般做法很简单

    @Override public void run() { Looper.prepare(); Looper.loop(); }

    prepare()和loop()两个方法不再赘述,我们先来看一个不用HandlerThread的例子:

    Thread newThread = new Thread(new Runnable() { @Override public void run() { Looper.prepare(); Looper.loop(); } }); newThread.start(); Handler handler = new Handler(newThread.getLooper());

    相信不少人会用上面的方式创建一个异步线程的Handler,有没有问题呢?肯定有。newThread的looper是在这个线程运行之后创建的,所以,当执行到Handler handler = new Handler(newThread.getLooper());的时候,newThread的looper可能还没有创建好!这就是为什么我们需要HandlerThread,并不仅仅是因为它帮我们创建了一个looper,更重要的是它为我们处理了这个异步问题。来看下HandlerThread的实现:

    @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; }

    简单的一个加锁帮我们做了最重要的事情。

    有人问我在run()方法里面,mTid开始赋值Process.myTid(),为什么后来又复制-1了呢?仔细想一下就有答案了,因为Looper.loop()是个死循环啊,执行到mTid = -1的时候,就是looper退出的时候。

    插一句,这个mTid是干嘛的?

    /** * Returns the identifier of this thread. See Process.myTid(). */ public int getThreadId() { return mTid; }

    Thread里面是没有getThreadId()方法的,Process.myTid()方法定义如下:

    /** * Returns the identifier of the calling thread, which be used with * {@link #setThreadPriority(int, int)}. */ public static final int myTid() { return Libcore.os.gettid(); }

    原来tid是修改线程优先级、调度策略时用来做线程唯一标识的。那么在HandleThread中,把mTid置为-1是几个意思?笔者的理解是,HandlerThread本身是为looper服务的,looper终止以后,线程也会马上终止,为防止开发者错误使用,所以将mTid置为-1。

    关于HandlerThread另外一个容易忽略的问题就是退出Looper。Looper通过quit()和quitSafely()方法退出(记得,Looper.loop()之后是一个死循环),看看Looper的loop()方法的注释

    /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop()

    Looper使用完毕执行quit本身就是一件容易忽略的事情,如果放到HandlerThread中,更是容易忘得一干二净。所以HandlerThread为我们提供了两个相同的方法:

    public boolean quit(){} public boolean quitSafely(){}

    不过说到底,维护Looper的生命周期还是我们每个开发者自己的事情,HandlerThread只不过是封装了一下,帮我们处理一个异步问题罢了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值