Android系统中异步消息处理线程机制的理解

Android系统中异步消息处理线程机制的理解

 普通线程:对于一般的线程模型,执行完run()方法内的代码后线程就结束了。
 异步线程:线程启动后会进入一个无限的循环体之中,每次循环,从其内部的消息队列中取出一个消息,并回调相应的消息处理函数,执行完一个消息后继续循环。如果消息队列为空,线程会暂停,直到消息队列中有新的消息。
 异步消息处理本质是仍然是一个线程,只不过这个线程的执行代码逻辑被设置成了异步线程模型所需要的。
 异步线程的应用需求:
1)任务需要常驻。比如处理用户交互,网络请求处理等任务。
2)任务需要根据外部传递的消息做不同的操作。比如,根据不同消息,对不同任务的分发等
 
 Android系统中的实现机制:
 
  在android中实现异步线程主要涉及到如下几个类:ThreadLocal,Looper,MessageQueue,Handler,Message。
 下面是网上的一张异步线程实现类的关系图:

ThreadLocal

ThreadLocal并不是Android的sdk中的类,而是java.lang中的一个类,该类的作用是为线程创建一个基于线程的变量存储,称之为线程局部存储

简单的说,就是作用域在线程内,本线程内的该类的任何对象保持一致。

ThreadLocal可以使对象达到线程隔离的目的,它为每一个线程维护自己的变量拷贝,通过其中的set方法将变量绑定到线程上。ThreadLocal提供了一种解决多线程同步的问题解决方案,通过为每一份变量进行拷贝,这样的话,每个线程操作的都是属于自己的变量,而不是共同的一个变量,因此也就不需要同步锁了。在Android的异步线程中,ThreadLocal绑定的这个线程变量就是Looper的一个对象。

Looper类

Looper只是产生一个消息循环框架,首先Looper创建了消息队列(MessageQueue)并把它挂接在Linux的线程上下文中,进入到取消息,并分发消息的循环当中Looper 类用来为一个线程跑一个消息循环。线程在默认情况下是没有消息循环与之关联的,Thread类在run()方法中的内容执行完之后就退出了,即线程做完自己的工作之后就结束了,没有循环的概念。

在Looper类中有一个成员变量mQueue(MessageQueue类的实例),该变量用于保存Looper中MessageQueue。 Looper通过静态方法Looper.prepare()方法来创建出一个MessageQueue对象。调用Looper类的 prepare() 方法可以为当前线程创建一个消息循环,调用loop() 方法使之处理信息,直到循环结束。注意,Looper.prepare()方法在一个线程中只能执行一次。大多数和消息循环的交互是通过 Handler 类进行的。

 class LooperThread extends Thread {
      public Handler mHandler;
      public void run() {
          Looper.prepare();
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
          Looper.loop();
      }
  }

Handler类  

  

Handler类用来发送和处理消息(Message)以及和线程的消息队列(MessageQueue)关联的Runnable对象。Handler对象在同一个线程上下文中取得消息队列,对消息队列进行封装操作,最主要的就是SendMessage和担当起dispatchMessage这个实际工作。

外部系统需要向某个Android线程发送消息,必须通过属于该AndroidThread的Handler这个对象每一个Handler对象都仅和一个线程及这个线程的消息队列关联。一个特定线程的所有Handler对象都会收到同样的方法。(这是一个“一对多”的关系)。如下图(图片来自网络)所示:


  当你创建一个新的Handler对象,它会和创建它的这个线程/线程的消息队列绑定,从那个时刻开始,它将向这个消息队列传递消息和runnable对象,并且当它们从队列中出来时执行它们。

  Handler主要有两种用途:

  1.合理调度安排消息和runnable对象,使它们在将来的某个点被执行。

  2.将一个动作入队安排在非当前线程执行。

Handler属于某个线程,取决Handlerd对象在哪个线程中建立Handler在构建时做了如下的默认动作:

  • 从线程上下文取得Looper
 
  • 通过Looper获取到消息队列并记录在自己的成员mQueue变量中


Handler使用消息队列进行对象封装,提供如下的成员函数:

  • 通过  post(Runnable r)发送。Runnable是消息处理的回调函数,通过该消息的发送,引起Runable 的回调运行,post消息放置消息队列的前面。Message.callback=Runable.
 
  • 通过 sendMessage发送。放置在所有的Post消息之后,sendMessage发送消息.

  • dispatchMessage分发消息。消息带有回调函数,则执行消息回调函数,如何没有则使用默认处理函数:handleMessage。而handleMessage往往被重载成某个继承
     Handler对象的新的特定的handleMessage。几乎所有的Message发送时,都指定了target。Message.target=(this).
Handler对象的post方法和sendMessage方法本质上都是发送消息的方法(post类方法实质上是调用了sendMessage方法)。所谓发送消息就是把消息放入消息队列中的合适位置,并且把消息的target设置为本Handler对象
所以当队列中的消息处理的时候,也会找到当时送它来的Handler对象,调用其相应的dispatchMessage()方法,进而调用其中的handleMessage()方法或者mCallback成员的handleMessage()方法来进行处理。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章