Как создать поток Looper, а затем немедленно отправить ему сообщение?

У меня есть рабочий поток, который находится в фоновом режиме и обрабатывает сообщения. Примерно так:

class Worker extends Thread {

    public volatile Handler handler; // actually private, of course

    public void run() {
        Looper.prepare();
        mHandler = new Handler() { // the Handler hooks up to the current Thread
            public boolean handleMessage(Message msg) {
                // ...
            }
        };
        Looper.loop();
    }
}

Из основного потока (потока пользовательского интерфейса, не то чтобы это важно) я хотел бы сделать что-то вроде этого:

Worker worker = new Worker();
worker.start();
worker.handler.sendMessage(...);

Проблема в том, что это настраивает меня на красивое состояние гонки: в то время worker.handler , невозможно быть уверенным, что рабочий поток уже назначен этому полю!

Я не могу просто создать обработчик Handler из Worker , потому что конструктор работает в основном потоке, поэтому обработчик ассоциирует себя с неправильным потоком.

Это вряд ли кажется необычным сценарием. Я могу придумать несколько обходных путей, и все они ужасны: публичный обработчик volatile Handler; // на самом деле частный, конечно public void run () { Looper.prepare (); mHandler = new Handler () {// Обработчик подключается к текущему потоку public boolean handleMessage (сообщение сообщение) { // ... } }; notifyAll (); // <- ДОБАВЛЕНО Looper.loop (); } }

И из основного потока:

 Worker worker = new Worker ();
worker.start ();
worker.wait (); // <- ДОБАВЛЕНО
worker.handler.sendMessage (...);

Но это тоже ненадежно: если notifyAll () произойдет до wait () , то нас никогда не разбудят!

  • Передача начального Сообщение конструктору Worker , отправив его методом run () . Специальное решение не будет работать для нескольких сообщений, или если мы не хотим отправлять его сразу, но вскоре после этого.

  • Занят-ожидание, пока поле обработчика больше не будет ноль . Да, в крайнем случае ...

  • Я хотел бы создать Handler и MessageQueue от имени потока Worker , но это не похоже быть возможным. Каков самый элегантный выход из этого?

    73
    задан Thomas 29 January 2011 в 17:18
    поделиться