处理程序queueIdle在最后一条消息到达之前调用两次

时间:2015-02-24 12:28:21

标签: android multithreading

我正在阅读EAT书籍,并且有一个显示queueIdle利用率的代码示例。

下面的代码启动10个线程,每个新线程抛出10个消息。而且我希望在发送每条消息后,looper将被退出。

@Override
public boolean queueIdle() {
    if (mIsFirstIdle) {
       mIsFirstIdle = false;
       return true;
    }

    mConsumerHandler.getLooper().quit();
    return false;
}
  

“空闲插槽可以在第一条消息之前,消息之间发生,   并在最后一条消息之后。 “摘录自:AndersGöransson。   “高效的Android线程。”iBooks。

所以我认为,queueIdle将使用第一条消息和最后一条消息进行调用,因此它确保每条消息都会被传递。

但我得到了以下错误,因为queueIdle意外调用了??

  

在死线程上向处理程序发送消息

是正常还是示例代码错了?

代码示例

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.os.SystemClock;
import android.util.Log;

import java.util.Random;


public class ConsumeAndQuitThreadActivity extends Activity {


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final ConsumeAndQuitThread consumeAndQuitThread = new ConsumeAndQuitThread();
        consumeAndQuitThread.start();

        for (int i = 0; i < 10; i++) {
            Log.v("EATDEGUB","thread " + i + " started.");

            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        Log.v("EATDEGUB","currentThread  "+ Thread.currentThread().getId() +  "  : enqueueData is " + i);
                        SystemClock.sleep(new Random().nextInt(10));
                        consumeAndQuitThread.enqueueData(i);
                    }
                }
            }).start();
        }
    }

    private static class ConsumeAndQuitThread extends Thread implements MessageQueue.IdleHandler {

        private static final String THREAD_NAME = "ConsumeAndQuitThread";

        public Handler mConsumerHandler;
        private boolean mIsFirstIdle = true;

        public ConsumeAndQuitThread() {
            super(THREAD_NAME);
        }

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

            mConsumerHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    //mIsFirstIdle=true;
                    Log.v("EATDEGUB","handled message is " + msg.what);
                }
            };

            Looper.myQueue().addIdleHandler(this);
            Looper.loop();
        }


        @Override
        public boolean queueIdle() {
            Log.v("EATDEGUB","Thread " +currentThread().getId());

            if (mIsFirstIdle) {
                mIsFirstIdle = false;
                return true;
            }

            Log.v("EATDEGUB", "Thread " +currentThread().getId() + " is closed by calling quit()");


    mConsumerHandler.getLooper().quit();
        return false;
    }

    public void enqueueData(int i) {
        mConsumerHandler.sendEmptyMessage(i);
    }
}

}

日志

02-24 13:54:41.490    thread 0 started.
02-24 13:54:41.490    Thread 9590
02-24 13:54:41.490    thread 1 started.
02-24 13:54:41.490    thread 2 started.
02-24 13:54:41.490    currentThread  9592  : enqueueData is 0
02-24 13:54:41.490    currentThread  9591  : enqueueData is 0
02-24 13:54:41.490    thread 3 started.
02-24 13:54:41.490    currentThread  9593  : enqueueData is 0
02-24 13:54:41.490    thread 4 started.
02-24 13:54:41.490    currentThread  9594  : enqueueData is 0
02-24 13:54:41.490    thread 5 started.
02-24 13:54:41.490    currentThread  9595  : enqueueData is 0
02-24 13:54:41.495    thread 6 started.
02-24 13:54:41.495    currentThread  9596  : enqueueData is 0
02-24 13:54:41.495    thread 7 started.
02-24 13:54:41.495    thread 8 started.
02-24 13:54:41.495    currentThread  9597  : enqueueData is 0
02-24 13:54:41.495    currentThread  9598  : enqueueData is 0
02-24 13:54:41.495    thread 9 started.
02-24 13:54:41.495    currentThread  9599  : enqueueData is 0
02-24 13:54:41.495    currentThread  9600  : enqueueData is 0
02-24 13:54:41.495    currentThread  9598  : enqueueData is 1
02-24 13:54:41.495    handled message is 0
02-24 13:54:41.495    Thread 9590

**02-24 13:54:41.495    Thread 9590 is closed by calling quit()**

After this time, none of remaining message can be delivered. >>

02-24 13:54:41.500    currentThread  9592  : enqueueData is 1
02-24 13:54:41.500    currentThread  9591  : enqueueData is 1
02-24 13:54:41.500    currentThread  9593  : enqueueData is 1
02-24 13:54:41.505    currentThread  9597  : enqueueData is 1
02-24 13:54:41.505    currentThread  9594  : enqueueData is 1
02-24 13:54:41.505    currentThread  9595  : enqueueData is 1
02-24 13:54:41.505    currentThread  9596  : enqueueData is 1
02-24 13:54:41.510    currentThread  9600  : enqueueData is 1
02-24 13:54:41.510    currentThread  9599  : enqueueData is 1
02-24 13:54:41.510    currentThread  9592  : enqueueData is 2
02-24 13:54:41.510    currentThread  9598  : enqueueData is 2
02-24 13:54:41.515    currentThread  9593  : enqueueData is 2
02-24 13:54:41.515    currentThread  9596  : enqueueData is 2
02-24 13:54:41.515    currentThread  9591  : enqueueData is 2
02-24 13:54:41.520    currentThread  9595  : enqueueData is 2
02-24 13:54:41.520    currentThread  9600  : enqueueData is 2
02-24 13:54:41.520    currentThread  9599  : enqueueData is 2
02-24 13:54:41.520    currentThread  9594  : enqueueData is 2
02-24 13:54:41.525    currentThread  9592  : enqueueData is 3
02-24 13:54:41.525    currentThread  9597  : enqueueData is 2
02-24 13:54:41.530    currentThread  9593  : enqueueData is 3
02-24 13:54:41.530    currentThread  9591  : enqueueData is 3
02-24 13:54:41.530    currentThread  9596  : enqueueData is 3
02-24 13:54:41.530    currentThread  9598  : enqueueData is 3
02-24 13:54:41.530    currentThread  9600  : enqueueData is 3
02-24 13:54:41.535    currentThread  9595  : enqueueData is 3
02-24 13:54:41.535    currentThread  9596  : enqueueData is 4
02-24 13:54:41.535    currentThread  9594  : enqueueData is 3
02-24 13:54:41.535    currentThread  9593  : enqueueData is 4
02-24 13:54:41.535    currentThread  9591  : enqueueData is 4
02-24 13:54:41.535    currentThread  9597  : enqueueData is 3
02-24 13:54:41.540    currentThread  9592  : enqueueData is 4
02-24 13:54:41.540    currentThread  9599  : enqueueData is 3
02-24 13:54:41.540    currentThread  9599  : enqueueData is 4
02-24 13:54:41.540    currentThread  9591  : enqueueData is 5
02-24 13:54:41.545    currentThread  9593  : enqueueData is 5
02-24 13:54:41.545    currentThread  9598  : enqueueData is 4
02-24 13:54:41.545    currentThread  9598  : enqueueData is 5
02-24 13:54:41.545    currentThread  9596  : enqueueData is 5
02-24 13:54:41.550    currentThread  9594  : enqueueData is 4
02-24 13:54:41.550    currentThread  9595  : enqueueData is 4
02-24 13:54:41.550    currentThread  9600  : enqueueData is 4
02-24 13:54:41.555    currentThread  9591  : enqueueData is 6
02-24 13:54:41.565    currentThread  9597  : enqueueData is 4
02-24 13:54:41.565    currentThread  9591  : enqueueData is 7
02-24 13:54:41.565    currentThread  9599  : enqueueData is 5
02-24 13:54:41.565    currentThread  9593  : enqueueData is 6
02-24 13:54:41.565    currentThread  9596  : enqueueData is 6
02-24 13:54:41.565    currentThread  9594  : enqueueData is 5
02-24 13:54:41.565    currentThread  9598  : enqueueData is 6
02-24 13:54:41.570    currentThread  9595  : enqueueData is 5
02-24 13:54:41.570    currentThread  9600  : enqueueData is 5
02-24 13:54:41.570    currentThread  9592  : enqueueData is 5
02-24 13:54:41.575    currentThread  9599  : enqueueData is 6
02-24 13:54:41.575    currentThread  9598  : enqueueData is 7
02-24 13:54:41.575    currentThread  9591  : enqueueData is 8
02-24 13:54:41.575    currentThread  9592  : enqueueData is 6
02-24 13:54:41.575    currentThread  9593  : enqueueData is 7
02-24 13:54:41.575    currentThread  9594  : enqueueData is 6
02-24 13:54:41.575    currentThread  9600  : enqueueData is 6
02-24 13:54:41.580    currentThread  9595  : enqueueData is 6
02-24 13:54:41.580    currentThread  9592  : enqueueData is 7
02-24 13:54:41.580    currentThread  9596  : enqueueData is 7
02-24 13:54:41.580    currentThread  9599  : enqueueData is 7
02-24 13:54:41.580    currentThread  9600  : enqueueData is 7
02-24 13:54:41.585    currentThread  9597  : enqueueData is 5
02-24 13:54:41.585    currentThread  9593  : enqueueData is 8
02-24 13:54:41.585    currentThread  9598  : enqueueData is 8
02-24 13:54:41.585    currentThread  9592  : enqueueData is 8
02-24 13:54:41.585    currentThread  9591  : enqueueData is 9
02-24 13:54:41.585    currentThread  9594  : enqueueData is 7
02-24 13:54:41.585    currentThread  9593  : enqueueData is 9
02-24 13:54:41.590    currentThread  9595  : enqueueData is 7
02-24 13:54:41.590    currentThread  9596  : enqueueData is 8
02-24 13:54:41.590    currentThread  9598  : enqueueData is 9
02-24 13:54:41.595    currentThread  9600  : enqueueData is 8
02-24 13:54:41.595    currentThread  9595  : enqueueData is 8
02-24 13:54:41.600    currentThread  9599  : enqueueData is 8
02-24 13:54:41.600    currentThread  9596  : enqueueData is 9
02-24 13:54:41.600    currentThread  9594  : enqueueData is 8
02-24 13:54:41.600    currentThread  9592  : enqueueData is 9
02-24 13:54:41.600    currentThread  9597  : enqueueData is 6
02-24 13:54:41.600    currentThread  9597  : enqueueData is 7
02-24 13:54:41.605    currentThread  9600  : enqueueData is 9
02-24 13:54:41.605    currentThread  9594  : enqueueData is 9
02-24 13:54:41.605    currentThread  9595  : enqueueData is 9
02-24 13:54:41.605    currentThread  9599  : enqueueData is 9
02-24 13:54:41.610    currentThread  9597  : enqueueData is 8
02-24 13:54:41.615    currentThread  9597  : enqueueData is 9

1 个答案:

答案 0 :(得分:0)

一年后;)我正在读这本书并且有完全相同的问题。

我的猜测是 sleep 的行正在引入空闲时间

SystemClock.sleep(new Random().nextInt(10));

第二次检测到空闲时间时,MessageQueue调用queueIdle来杀死处理程序并返回false。从现在开始,对sendMessage的所有调用都将在Handler和一个不再存在的Thread上完成,因此错误。

这是我的猜测所以我删除 sleep 的行并启动了应用程序:有时它可以正常工作,但大部分时间错误仍然存​​在。所以我的猜测是错误的,或者出于不同的原因可能会出现空闲时间。