线程间通信原理

来源:互联网 发布:合同登记软件 编辑:程序博客网 时间:2024/06/01 11:50

     首先我们先来看一下线程间通信原理的流程图:

线程间通信原理:

      1.Android是单线程模型,单线程的好处是避免代码重复和效率低。
      2.主线程负责更新UI,工作线程不能更新UI。
      3.工作线程执行耗时操作,避免主线程堵塞。
      4.主线程通过Looper遍历消息队列,有消息处理,没消息休息。

Message类:

       用于存放线程间通信所需的消息,包括代码。重要的属性包括:

                          target属性:   存放收发该消息的Handler对象

                          callback属性: 存放Runnabule对象

                          what属性:     int类型,表示消息的类型,用于区分不同类型的消息

                          arg1属性:     存放消息中类型是int数据

                          arg2属性:     存放消息中类型是int数据     
               
                          obj属性:      Object类型,存放消息中任意类型的数据 

                          data属性:     Bundle类型,存放任意类型的数据

Handler类:

          Android通过Handler类实现线程间收发消息。Handler原意是“操作者”。Android是单线程模型,只有主线程才能更新UI,工作线程更新UI需要用Handler将数据发送给主线程来更新UI。Handler负责在其它线程发送消息,同时在本线程接受处理消息。线程和Handler是一对多的关系,一个线程可以对应多个Handler,但一个Handler只能为一个线程服务。

关于Handler类的构造器:

              无参构造器:

                创建为当前线程工作的Handler对象,并实现HandlerMessage方法

                       public Handler(Callback callback){
                           this (callback,false); 
                       }

                创建与指定Looper绑定的Handler对象

                       public Handler(Looper looper){
                              this(looper,null,false);
                       }  

                创建与指定Looper绑定的Handler对象,并实现HandlerMessage方法

                       public Handler(Looper looper,Callback callback){
                              this(Looper,callback,false);
                       }   

Handler发送消息:

 post方法发送一段代码

        post源码:

                      
   
        getPostMessage方法源码:

                      
         
        sendMessageDelayed方法源码:

                       

        sendMessageAtTime方法源码:

                     

   sendMessage方法源码:
                    
                

Handller处理消息:

    Handler类通过dispatchMessage方法将消息队列中取出的消息分发给相关方法处理。

    dispatchMessage方法分发消息的流程:     
          
            dispatchMessage方法源码:
                 

            handleCallback方法源码:
 
                 
     
      关于Callback接口:它是Handler类的内部接口,在Message.callback中使用。
         
           Callback接口源码:
                     

      为什么我们要用Callback接口?Handler有一个带有Callback的构造方法,通过该方法创建Handller对象,可以避免创建Handler的子类时,复写handleMessage。执行Handler.mCallback.handleMessage方法,就可使用Callback接口。


Looper类:

     Looper是实现Android线程间通信重要的一个类,Android为主线程自动创建一个Looper。Looper用于为指定线程创建并维护一个消息队列,用先进先出的方式从消息队列中取出消息,交给Handler处理。工作线程默认没有Looper和消息循环,一个线程只能有一个Looper。

    Looper的创建:
           Looper由Looper.prepare方法创建,不能直接new。
                      public static void prepare(){
                           prepare(true);
                      }
     
         
        ThreadLocal允许每个线程都创建一份自己的局部变量。ThreadLocall是泛型类,sThreadLocal用于为每个线程保存一个Looper对象。ThreadLocal通过set方法将与当前线程相关联的LLooper对象保存在ThreadLocal(Map集合中)。ThreadLocal通过get方法将与当前线程相关联的Looper对象中ThreadLocal(Map集合中)取出。
        quiteAllowed:
        为主线程创建Looper的prepareMainLooper方法。
        工作线程在创建时,必须设置quietAllowed为true,允许Looper.quit结束Looper对消息队列的遍历。但主线程的Looper在创建时,quitAllowed必须设置为false,即不允许主线程中的Looper退出。

遍历消息队列:
         Looper.loop方法用于遍历消息队列。(源码就不贴出来了)

常见方法: 
         Looper.myLooper(),得到当前线程的looper对象。
         getThread(),得到looper对象所属线程。
         quit(),结束looper循环,主线程不能调用本方法。

MessageQueue类:

           是一个低等级的持有Messages集合的类,被ooper分发,Message会发送到与Hanlder所绑定的MessageQueue中通过Looper.myQueue()方法来检索当前线程的MessageQueue。(数据结构是先进先出的队列)。
     
           常用方法:
               enqueueMessage方法:将Message入队列。用于链表实现队列,并用无限循环遍历队列中的消息。
               next方法:从队列中取出Message。next用无限循环遍历消息队列,取出消息。

Android中HandlerThread类和AsyncTask类封装了消息循环机制。

handler通信机制中的 Looper.loop方法中调用queue.next()实现阻塞的原理?
          主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。
          Handler机制是使用pipe(Linux中的管道)来实现的,没有消息处理时主线程会在管道的读端阻塞;
     有消息时,Binder线程往主线程消息队列里添加消息,然后会往管道写端写一个字节,以此来唤醒主线程从管道读端返回,      也就是说queue.next()会调用返回。