android多线程三(Message,MessageQueue)

Message 定义一个包含任意类型的描述数据对象,此对象可以发送给Handler。

尽管Message的构造器是公开的,但是获取Message对象的最好方法是调用Message.obtain()或者Handler.obtainMessage(), 这样是从一个可回收对象池中获取Message对象


Message类是个final类,就是说不能被继承,同时Message类实现了Parcelable接口.

what,arg1,arg2,obj,这些常用到的变量就不多少了,我们来看看一些不常见的,

    /*package*/ Bundle data;  
      
    /*package*/ Handler target;       
      
    /*package*/ Runnable callback;     
      
    // sometimes we store linked lists of these things  
    /*package*/ Message next;  
  
    private static final Object sPoolSync = new Object();  
    private static Message sPool;  
    private static int sPoolSize = 0;  
  
    private static final int MAX_POOL_SIZE = 10; 

Message是通过一个message pool(消息池)来存储消息资源的,默认这个池子的大小是10个消息资源。

/**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
这里可以看到,使用obtain()方法,会从池子里获取一个消息。 当没有可用的空余资源时,new一个。


当looper处理完一个消息时,调用的recyle:

    /**
     * Return a Message instance to the global pool.  You MUST NOT touch
     * the Message after calling this function -- it has effectively been
     * freed.
     */
    public void recycle() {
        clearForRecycle();

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

这里的意思就是,当looper用完一个消息后,调用recycle,当当前的pool size没达到MAX_POOL_SIZE的时候,将此消息归还给消息池子。


我们来图示一下这个message pool(实际上是recycle回来的用于再利用的)。


这也是个后进先出的队列,始终是操作sPool,实在也没必要关心这个,池子里有东西取,有地方放就Ok了。


还有就是Message的sendToTarget方法的实质还是用handler来sendMessage。

    /**
     * Sends this Message to the Handler specified by {@link #getTarget}.
     * Throws a null pointer exception if this field has not been set.
     */
    public void sendToTarget() {
        target.sendMessage(this);
    }


MessageQueue

MessageQueue里面有一个收到的Message的对列:


上层代码通过Handler的sendMessage等函数放入一个message到MessageQueue里面时最终会调用MessageQueue的 enqueueMessage函数。enqueueMessage根据上面的接收的Message的队列的构造把接收到的Message放入队列中。 

消息入队列的方法。

final boolean enqueueMessage(Message msg, long when) { //参数when为消息的延迟时间量 
        ........
        synchronized (this) {
            ................
            msg.when = when;
            //Log.d("MessageQueue", "Enqueing: " + msg);
            Message p = mMessages;
            if (p == null || when == 0 || when < p.when) {
               //如果待入队列消息的延迟时间为0(立即执行)或比队列顶部消息的延迟时间少,则此待入队列消息放到队列顶部 
                msg.next = p;
                mMessages = msg;
                this.notify();
            } else {
               //否则,从头遍历链表,查找到第一个延迟时间比待入队消息长的消息,将待入队消息插入这个消息之前
                Message prev = null;
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
                msg.next = prev.next;
                prev.next = msg;
                this.notify();
            }
        }
        return true;
    }  
获取队列中的下一个消息:遍历消息队列,返回一个可以在当前时间处理的消息,如果找不到这样的一个消息,则阻塞当前线程,直到出现一个可以处理的消息为止。   

final Message next() {
        int pendingIdleHandlerCount = -1; // 空闲的handler个数,只有第一次循环的时候是-1
        int nextPollTimeoutMillis = 0;//下次轮询时间

        for (;;) {
            if (nextPollTimeoutMillis != 0) {//如果轮询时间不为0,执行等待消息
                Binder.flushPendingCommands();
            }
            nativePollOnce(mPtr, nextPollTimeoutMillis);//native层的工作,没有深究,TODO

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                final Message msg = mMessages;
                if (msg != null) {
                    final long when = msg.when;
                    if (now >= when) {//此时有Message需要执行
                        mBlocked = false;
                        mMessages = msg.next;
                        msg.next = null;
                        if (false) Log.v("MessageQueue", "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    } else {//重置下次的轮询的时间
                        nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
                    }
                } else {
                    nextPollTimeoutMillis = -1;
                }

                // If first time, then get the number of idlers to run.
                if (pendingIdleHandlerCount < 0) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount == 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.处理空闲处理器
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {//执行接口回调
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf("MessageQueue", "IdleHandler threw exception", t);
                }

                if (!keep) {//根据状态执行删除操作
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;

            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

其中有个接口

  /**
     * Callback interface for discovering when a thread is going to block
     * waiting for more messages.
     *  当线程进入阻塞前,执行此回调接口。这个接口提供了一个机制可以在线程为了等待可处理消息,而进入阻塞前,执行一些处理(比如生产入队一个可处理的消息)。 
     */
    public static interface IdleHandler {
        /**
         * Called when the message queue has run out of messages and will now
         * wait for more.  Return true to keep your idle handler active, false
         * to have it removed.  This may be called if there are still messages
         * pending in the queue, but they are all scheduled to be dispatched
         * after the current time.
         * 当消息队列中没有可在当前时间处理的消息并且要进入阻塞等待出现可以处理的消息(比如:当前队列中所以的消息都是计划在当前时间之后执行的)时,调用此方法。
           返回true,使这个接口实例保持活动;false,这个接口实例将从接口实例类表中移除(这个接口列表是每次)。 
         */
        boolean queueIdle();
    }


接下来是删除,
MessageQueue的removeMessages函数根据上面的接收的Message的队列的构造把接收到的Message从队列中删除,并且调用对应Message对象的recycle函数把不用的Message放入Message Pool中。 

final boolean removeMessages(Handler h, int what, Object object,
            boolean doRemove) {
        synchronized (this) {
            Message p = mMessages;
            boolean found = false;

            // Remove all messages at front.
            while (p != null && p.target == h && p.what == what
                   && (object == null || p.obj == object)) {
                if (!doRemove) return true;
                found = true;
                Message n = p.next;
                mMessages = n;
                p.recycle();
                p = n;
            }

            // Remove all messages after front.
            while (p != null) {
                Message n = p.next;
                if (n != null) {
                    if (n.target == h && n.what == what
                        && (object == null || n.obj == object)) {
                        if (!doRemove) return true;
                        found = true;
                        Message nn = n.next;
                        n.recycle();
                        p.next = nn;
                        continue;
                    }
                }
                p = n;
            }
            
            return found;
        }
    }


当初有担心如果remove一个正在执行的message会怎么样呢,看过源码中的同步锁就不会再有这个担心了。


最后图示下过程:

android多线程三(Message,MessageQueue)_第1张图片

其中清理Message是Looper里面的loop函数指把处理过的Message放到Message的Pool里面去,如果里面已经超过最大值10个,则丢弃这个Message对象。 
调用Handler是指Looper里面的loop函数从MessageQueue的接收消息队列里面取出消息,然后根据消息指向的Handler对象调用其对应的处理方法。 



参考:http://blog.csdn.net/aomandeshangxiao/article/details/8169884

http://qaohao.iteye.com/blog/509145

http://czpsailer.iteye.com/blog/655942

你可能感兴趣的:(android多线程三(Message,MessageQueue))