如何创建一个弯针线,然后立即发送一条消息? [英] How to create a Looper thread, then send it a message immediately?
问题描述
我有一个工作线程坐在后台,处理消息。事情是这样的:
I have a worker thread that sits in the background, processing messages. Something like this:
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();
}
}
在主线程(UI线程,这不是问题),我愿做这样的事情:
From the main thread (UI thread, not that it matters) I would like to do something like this:
Worker worker = new Worker();
worker.start();
worker.handler.sendMessage(...);
麻烦的是,这台我一个美丽的竞态条件:在时间 worker.handler
读,没有办法,以确保工作线程已经分配到这个领域!
The trouble is that this sets me up for a beautiful race condition: at the time worker.handler
is read, there is no way to be sure that the worker thread has already assigned to this field!
我不能简单地创建处理程序
从工人
的构造函数,因为构造的主线程上运行,所以处理程序
将自己与错误的线程关联起来。
I cannot simply create the Handler
from the Worker
's constructor, because the constructor runs on the main thread, so the Handler
will associate itself with the wrong thread.
这似乎很难像一个罕见的情景。我能想出一些解决方法,所有这些丑陋的:
This hardly seems like an uncommon scenario. I can come up with several workarounds, all of them ugly:
-
事情是这样的:
Something like this:
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的()
发生之前的等待()
,那我们我将永远不会被唤醒!
But this is not reliable either: if the notifyAll()
happens before the wait()
, then we'll never be woken up!
传递初始消息
到工人
的构造,具有的run()
办法发布。一个临时的解决方案,不会为多条消息的工作,或者如果我们不想把它右走,但不久之后。
Passing an initial Message
to the Worker
's constructor, having the run()
method post it. An ad-hoc solution, won't work for multiple messages, or if we don't want to send it right away but soon after.
忙等待,直到处理
字段不再空
。是的,不得已......
Busy-waiting until the handler
field is no longer null
. Yep, a last resort...
我想创建一个处理程序
和 MessageQueue
代表工人的
话题,但是这似乎并不可能。什么是最优雅的出路呢?
I would like to create a Handler
and MessageQueue
on behalf of the Worker
thread, but this does not seem to be possible. What is the most elegant way out of this?
推荐答案
最终解决(减去错误检查),这要归功于CommonsWare:
Eventual solution (minus error checking), thanks to CommonsWare:
class Worker extends HandlerThread {
// ...
public synchronized void waitUntilReady() {
d_handler = new Handler(getLooper(), d_messageHandler);
}
}
和从主线程:
Worker worker = new Worker();
worker.start();
worker.waitUntilReady(); // <- ADDED
worker.handler.sendMessage(...);
该工程的感谢 HandlerThread.getLooper的语义()
的块,直到弯针已被初始化。
This works thanks to the semantics of HandlerThread.getLooper()
which blocks until the looper has been initialized.
顺便说一句,这是类似我的解决方案#1以上,因为 HandlerThread
的实施大致如下(爱是爱开放源码):
Incidentally, this is similar to my solution #1 above, since the HandlerThread
is implemented roughly as follows (gotta love open source):
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;
}
关键的区别在于,它不会检查工作线程运行,但它实际上已经创造了一个活套;并且这样做的方式是存储在打环器私有字段。不错!
The key difference is that it doesn't check whether the worker thread is running, but that it has actually created a looper; and the way to do so is to store the looper in a private field. Nice!
这篇关于如何创建一个弯针线,然后立即发送一条消息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!