在阻止后台线程时在后台线程中的主线程中运行代码

时间:2014-07-16 12:54:19

标签: android multithreading bluetooth

我在尝试在后台线程中调用主线程时遇到了一些问题。

根据这篇文章:Running code in main thread from another thread

解决方案应该是:

private void runOnMainThread() {
    new Handler(Looper.getMainLooper()).post(new Runnable() {

        @Override
        public void run() {
            // Do something
            ottoBus.post(new MyObjectEvent(mMyObject));

            // End do something
            mMyObject = null;
        }
    });
}

然而,我的后台线程仍然能够在"做某事"之间读取蓝牙套接字数据。和#34;结束做某事"

我在这里缺少什么?是否可以锁定后台线程,同时"做某事"正在执行?

我的读取套接字数据的代码如下:

InputStream stream = null;
InputStreamReader reader = null;
BufferedReader bufferedReader = null;
String data = "";

try {
    stream = mSocket.getInputStream();

    byte[] bytes = new byte[20];

    int numRead = 0;
    while ((numRead = stream.read(bytes)) >= 0) {
        String s = new String(bytes, 0, numRead);
        if (mMyObject != null) {
            fillData(s); // Can cause NPE
        } else {
            mMyObject = new MyObject();
            fillData(s);
        }

        // This should be synchronised call
        runOnMainThread();

感谢。

3 个答案:

答案 0 :(得分:2)

您需要使用名为wait/notify的Java模式。简单地说:它定义了两个线程, 生产者和消费者,以便消费者在启动生产者之后停止并等待生产者线程完成。

它是这样的:

static final object uiActionMonitor = new Object();
transient boolean uiCompleted;

void network_thread_run() {

    int numRead = 0;
    while ((numRead = stream.read(bytes)) >= 0) {
        String s = new String(bytes, 0, numRead);

    // This should be synchronised call
    uiCompleted = false;
    runOnMainThread();

    synchronized(uiActionMonitor) {  //<---------- wait for UI to complete
       while (!uiCompleted) {
            uiActionMonitor.wait();
       }
    }

}

UI代码:

private void runOnMainThread() {
    new Handler(Looper.getMainLooper()).post(new Runnable() {

        @Override
        public void run() {
            // Do something

            // End do something
            uiCompleted = true;
            synchronized(uiActionMonitor) {  //<---------- release networking thread
                uiActionMonitor.notifyAll();                 
            }
        }
    });
}

完全按原样复制同步逻辑。这是许多开发人员弄错的地方。

我必须承认,当UI线程正在处理您的消息时,我无法理解为什么需要阻止您的网络线程......

答案 1 :(得分:0)

我认为你需要使用锁或同步集团。您可以查看java concurency documentation以及更具体的thisthis部分。 通过这种方式,您可以保证代码的某些部分不会同时执行多个时间。

答案 2 :(得分:0)

我发现CountDownLatch是完成此类事情的最简单方法。这是一个可重用的方法,用于在主线程上运行Runnable并阻止它们完成:

private static final Handler mainHandler = new Handler(Looper.getMainLooper());

private static void runOnMainThreadBlocking(Runnable runnable) throws InterruptedException {
  CountDownLatch completionSignal = new CountDownLatch(1);

  mainHandler.post(new Runnable() {
    @Override public void run() {
      runnable.run();
      completionSignal.countDown();
    }
  });

  completionSignal.await();
}