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()
естественият код задава alive на 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, нишката ще бъде instanceof 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) ще уведоми всички нишки, които чакат нишката да приключи.