【问题标题】:Android Threads: is it necessary to wait for threads to start before "join"ing them?Android 线程:在“加入”线程之前是否有必要等待线程启动?
【发布时间】:2015-11-21 05:54:16
【问题描述】:

我正在实现一个 Android“服务”。在它的“onCreate”中,我想启动并等待另一个线程的完成。 ClientServiceLoop 是一个 Runnable,在 run() 中有一个 while(true) 循环,返回条件很简单。

@Override
public void onCreate() {
    super.onCreate();
    mClientServiceLoopThread = new Thread(mClientServiceLoop = new ClientServiceLoop(),
            "ClientServiceLoop");
    mClientServiceLoopThread.start();
    try {
        mClientServiceLoopThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

我想知道的是,在我调用 start() 之后,新生成的线程是否保证已经调用了 Runnable 的 run() 方法?在调用 join() 之前我应该​​等待线程启动吗?我无法找到有关确切保证这一点的文档。


测试一下,如果我不调用 start(),join() 会立即返回。我想知道的是什么时候 isAlive() 实际设置。我搜索了 Android sdk,但找不到设置 nativePeer 的位置。

--

    mClientServiceLoopThread = new Thread(mClientServiceLoop = new ClientServiceLoop(),
            "ClientServiceLoop");
    boolean b = mClientServiceLoopThread.isAlive(); // false
    try {
        mClientServiceLoopThread.join(); // internally just while(isAlive)...so returns immediately
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    mClientServiceLoopThread.start();//FIXME TESTING ONLY

-- 安卓源码

/**
 * Blocks the current Thread (<code>Thread.currentThread()</code>) until
 * the receiver finishes its execution and dies.
 *
 * @throws InterruptedException if the current thread has been interrupted.
 *         The interrupted status of the current thread will be cleared before the exception is
 *         thrown.
 * @see Object#notifyAll
 * @see java.lang.ThreadDeath
 */
public final void join() throws InterruptedException {
    synchronized (lock) {
        while (isAlive()) {
            lock.wait();
        }
    }
}


/**
 * Returns <code>true</code> if the receiver has already been started and
 * still runs code (hasn't died yet). Returns <code>false</code> either if
 * the receiver hasn't been started yet or if it has already started and run
 * to completion and died.
 *
 * @return a <code>boolean</code> indicating the liveness of the Thread
 * @see Thread#start
 */
public final boolean isAlive() {
    return (nativePeer != 0);
}

nativePeer 设置在哪里??

【问题讨论】:

    标签: android multithreading runnable


    【解决方案1】:

    好的,我明确地追踪到了这一点。似乎 nativeCreate() 在调用 pthread_create 之前设置了 nativePeer。由于 pthread_create() 无法保证线程在返回时已启动,因此我不确定 Android 是否以相同的方式运行。似乎他们已经处理了这件事。所以一旦 start() 被调用 join() 将保证等待。但是 join() 不会等待,除非 start() 被调用。

    https://android.googlesource.com/platform/art/+/3c50a4b4ba6d7d9369ee9a0bd6d30bf4c9c79bb0/src/thread.cc

    // Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to
    // assign it.
    env->SetIntField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
                   reinterpret_cast<jint>(child_thread));
    ...
    int pthread_create_result = pthread_create(&new_pthread, &attr, Thread::CreateCallback, child_thread);
    

    【讨论】:

      【解决方案2】:

      从技术上讲,您可以在致电start 之前致电join

      这里的问题是服务默认在应用程序的主线程(UI 线程)上执行代码。调用 join 会阻塞你的 UI 线程并使你的应用完全没有响应。

      不要这样做

      你可以让onCreate()在你启动线程后正常返回,Service不会被销毁。

      【讨论】:

      • 我决定对此进行测试。问题是,如果没有启动,似乎 join() 会立即返回。 (更新的原始帖子)
      【解决方案3】:

      当主线程调用mClientServiceLoopThread.join();它将停止运行并等待 mClientServiceLoopThread 线程完成,因此您可以安全地调用 start 然后加入。

      【讨论】:

      • 好的,两个答案都有道理。谢谢!
      猜你喜欢
      • 2016-11-01
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多