У меня есть рабочий поток, который работает в фоновом режиме и обрабатывает сообщения.Примерно так:
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
, потому что конструктор работает в главном потоке, поэтому Handler
будет ассоциироваться с неправильным потоком.
Это вряд ли кажется необычным сценарием.Я могу придумать несколько обходных путей, все они безобразны:
Примерно так:
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) {
// ...
}
};
notifyAll(); // <- ADDED
Looper.loop();
}
}
И из основного потока:
Worker worker = new Worker();
worker.start();
worker.wait(); // <- ADDED
worker.handler.sendMessage(...);
Но это также ненадежно: если notifyAll()
произойдет до wait()
, то мы никогда не проснемся!
Передача начального Message
вконструктор Worker
, имеющий метод run()
.Специальное решение, не будет работать для нескольких сообщений или если мы не хотим отправлять его сразу, но вскоре после этого.
Ожидание до handler
поле больше не null
.Да, последнее средство ...
Я хотел бы создать Handler
и MessageQueue
от имени потока Worker
, но это не представляется возможным,Какой самый элегантный выход из этого?