кто и когда уведомляет thread.wait (), когда вызывается thread.join ()? - PullRequest
6 голосов
/ 26 марта 2012

thread.join() вызовет thread.wait(), но кто и когда уведомит (либо с помощью thread.notify() или notifyAll()) thread.wait()?

Как мы знаем, соединение потока будет ожидать потокадолжно быть завершено, но кто звонит уведомить об этом?

Ответы [ 2 ]

7 голосов
/ 26 марта 2012

Изменить:

О, вы говорите внутри самого Thread объекта. Внутри join() мы видим wait(). Что-то вроде:

while (isAlive()) {
    wait(0);
}

notify() для этого обрабатывается подсистемой Thread. Когда метод run() завершается, notify() вызывается для объекта Thread. Я не уверен, что код, который на самом деле вызывает notify(), можно увидеть - кажется, это сделано в нативном коде.


Не нужно, чтобы пользовательский код вызывал notify() для этого Thread объекта. Код Java Thread обрабатывает это внутренне. После завершения потока вызов join() вернется.

Например, следующий код выполнится нормально, а вызов join() вернется нормально без вызовов wait() или notify().

Thread thread = new Thread(new Runnable() {
   public void run() {
      // no-op, just return immediately
   }
});
thread.start();
thread.join();

Важно отметить, что на такое поведение, вероятно, нельзя полагаться. Вызов notify() является внутренним для системы потоков. Вам следует использовать join(), если вы ожидаете окончания потока.

4 голосов
/ 28 июня 2017

Что касается jdk7 для Linux, вы можете получить ответ из исходного кода openjdk.

/ jdk7 / hotspot / src / os / linux / vm / os_linux.cpp

int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

static void *java_start(Thread *thread) {
  ...
  thread->run();
  return 0;
}

и при запуске потока в Java поток будет экземпляром JavaThread.

/ jdk7 / hotspot / src / share / vm / runtime / thread.cpp

void JavaThread::run() {
  ...
  thread_main_inner();
}

void JavaThread::thread_main_inner() {
  ...
  this->exit(false);
  delete this;
}

void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
  ...
  // Notify waiters on thread object. This has to be done after exit() is called
  // on the thread (if the thread is the last thread in a daemon ThreadGroup the
  // group should have the destroyed bit set before waiters are notified).
  ensure_join(this);
  ...
}

static void ensure_join(JavaThread* thread) {
  // We do not need to grap the Threads_lock, since we are operating on ourself.
  Handle threadObj(thread, thread->threadObj());
  assert(threadObj.not_null(), "java thread object must exist");
  ObjectLocker lock(threadObj, thread);
  // Ignore pending exception (ThreadDeath), since we are exiting anyway
  thread->clear_pending_exception();
  // Thread is exiting. So set thread_status field in  java.lang.Thread class to TERMINATED.
  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
  // Clear the native thread instance - this makes isAlive return false and allows the join()
  // to complete once we've done the notify_all below
  java_lang_Thread::set_thread(threadObj(), NULL);
  lock.notify_all(thread);
  // Ignore pending exception (ThreadDeath), since we are exiting anyway
  thread->clear_pending_exception();
}

, поэтому lock.notify_all (thread) уведомит все потоки, ожидающие завершения потока.

...