如何创建一个弯针线,然后立即发送一条消息? [英] How to create a Looper thread, then send it a message immediately?

查看:117
本文介绍了如何创建一个弯针线,然后立即发送一条消息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个工作线程坐在后台,处理消息。事情是这样的:

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:

  1. 事情是这样的:

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆