Nasıl Tetikçi bir iş parçacığı oluşturmak için bir mesajı hemen göndermek?
Arka plan, işlem iletileri oturur bir iş parçacığı var. Şöyle bir şey:
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();
}
}
Ana iş parçacığı (önemli olan UI iş parçacığı değil) böyle bir şey yapmak istiyorum:
Worker worker = new Worker();
worker.start();
worker.handler.sendMessage(...);
Sorun bu ayarlar benim için güzel bir yarış durumu: anda worker.handler
okuma imkanı yok emin olmak için bu iş parçacığı zaten atanan bu alan!
Sadece Worker
'kurucu ana iş parçacığı üzerinde çalıştığı için s yapıcı Handler
yanlış iş parçacığı ile kendisini ilişkilendirmek. dan Handler
oluşturun edemem
Bu pek nadir görülen bir senaryo gibi görünüyor. Birkaç geçici çözüm, hepsi çirkin buldum
Şöyle bir şey:
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(); } }
Ve esas konu:
Worker worker = new Worker(); worker.start(); worker.wait(); // <- ADDED worker.handler.sendMessage(...);
notifyAll()
wait()
, o zaman uyanmış olacağız önce olursa! ama bu değildir güvenilir ya da:Geçen
Worker
Message
bir ilk'ler,run()
yöntem sonrası sahip kurucu. Geçici bir çözüm, eğer hemen ama kısa bir süre sonra göndermek istemeyiz. eğer birden fazla ileti için çalışmak, ya da olmaz.handler
alana kadar meşgul bekleme artıknull
. Evet, son çare...
Worker
iplik adına Handler
MessageQueue
bir oluşturmak istiyorum, ama bu mümkün görünmüyor. Bu işten en zarif yolu nedir?
CEVAP
(Eksi hata denetimi) nihai çözüm, CommonsWare için teşekkürler
class Worker extends HandlerThread {
// ...
public synchronized void waitUntilReady() {
d_handler = new Handler(getLooper(), d_messageHandler);
}
}
Ve esas konu:
Worker worker = new Worker();
worker.start();
worker.waitUntilReady(); // <- ADDED
worker.handler.sendMessage(...);
Bu tetikçi başlatıldı kadar HandlerThread.getLooper()
blok semantiği sayesinde çalışıyor.
Bu arada, bu benim çözüm benzer HandlerThread
şöyle kabaca uygulanan açık kaynak aşk lazım () #1 Yukarıda
public void run() {
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Looper.loop();
}
public Looper getLooper() {
synchronized (this) {
while (mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
En önemli fark bu değil olup olmadığını kontrol edin worker çalışıyor, ama aslında oluşturulan bir looper; ve bu yüzden saklamak için looper özel bir alan. Güzel!
Nasıl bir görev (VUK) STA bir çalışan ...
Nasıl alfa-sayısal rasgele bir dize ol...
Nasıl bir dosyanın içeriğini bir Java ...
Nasıl terminalden Curl ile JSON veri g...
Nasıl bir bağlantı gibi davranan bir H...