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

来源:互联网 发布:csp 软件百度云 编辑:程序博客网 时间:2024/05/18 00:01
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()方法来进行处理。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 工商注册资金没有交怎么办 住公司宿舍怎么办居住证 住在公司宿舍怎么办居住证 滴滴没有的车型怎么办 假的租房合同怎么办 代注册公司被骗怎么办 公司跨区迁址怎么办 公司搬走注册地怎么办 注册公司没有房产证怎么办 公司不运营了怎么办 公司注销了账户怎么办 租户不变更地址怎么办 营业执照忘审了怎么办 工商营业执照年检过期怎么办 个体营业执照没有年报怎么办? 个体工商户一年没有申报怎么办 个体工商户逾期未申报怎么办 个体户没报税过怎么办 农业银行证书过期了怎么办 ca证书丢了怎么办 ca证书被锁怎么办 上个月忘记清卡怎么办 财务人员进入税务黑名单怎么办 社保本丢了怎么办 贷款车辆登记证书怎么办 发票薄丢了怎么办? 汽车发票丢了怎么办 税票弄丢了怎么办 交强险正本丢了怎么办 个体营业执照正本丢失怎么办 简易注销后税务怎么办 拒绝了日历邀请怎么办 老人走丢了怎么办 老人走丢找不到怎么办 没人给介绍对象怎么办 bate365账号被锁怎么办 qq号疑似被盗怎么办 不知道音乐名字怎么办 忘记支付宝登录怎么办 微信被老婆拉黑怎么办 微信群昵称改不了怎么办