thread.join()
позвонит thread.wait()
, но кто и когда уведомит (с помощью thread.notify()
или notifyAll()
) thread.wait()
?
Как мы знаем, присоединение к потоку будет ждать завершения потока, но кто вызывает уведомление об этом?
thread.join()
позвонит thread.wait()
, но кто и когда уведомит (с помощью thread.notify()
или notifyAll()
) thread.wait()
?
Как мы знаем, присоединение к потоку будет ждать завершения потока, но кто вызывает уведомление об этом?
Изменить:
О, вы говорите о самом объекте 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()
, если вы ждете завершения потока.
notify()
вызывается из подсистемы Thread
. Я не уверен, что вы видите этот код. Может быть, в родной стране.
- person Gray; 26.03.2012
while (isAlive()) { wait(0); }
. Он будет вызывать wait()
до тех пор, пока поток не перестанет существовать. В конце метода run()
собственный код устанавливает значение false и уведомляет метод Thread
.
- person Gray; 26.03.2012
Thread#join
действительно работает.
- person Tim Bender; 02.04.2012
Что касается 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) уведомит все потоки, ожидающие завершения потока.