Java中Thread类的join方法到底是如何实现等待的?

我看了一眼join方法的源码,无参数的join调用的是join(long millis)方法并传入参数0,join(long millis)源码的核心…
关注者
114
被浏览
20,110

7 个回答

锁在这里:

jdk8u/jdk8u/jdk: df209f221cca src/share/classes/java/lang/Thread.java
    public final synchronized void join(long millis)
    throws InterruptedException {

看到synchronized关键字了不?

好吧,我给楼主解释一下:

现在的场景是A线程执行:

public void run(){

bThread.join(0);//把b线程加入到当前线程(a线程),等待b结束,当前a线程才会结束.

}

B线程执行

public void run(){

for(int i=0;i<10000;i++)

lipMyAss();//亲我的屁股,哦~~亲

}

看join代码:

public final synchronized void join(long millis) throws InterruptedException {
	long base = System.currentTimeMillis();//获取当前时间
	long now = 0;

	if (millis < 0) {//判断不说了
	    throw new IllegalArgumentException("timeout value is negative");
	}

	if (millis == 0) {//这个分支是无限期等待直到b线程结束
		while (isAlive()) {
			wait(0);
		}
	} else {//这个分支是等待固定时间,如果b没结束,那么就不等待了。。。
		while (isAlive()) {
			long delay = millis - now;
			if (delay <= 0) {
				break;
			}
			wait(delay);
			now = System.currentTimeMillis() - base;
		}
	}
}

然后只说无限期等待的情况:

while (isAlive()) {
//只要线程还活着,我tm就等到天荒地老
	wait(0);//wati操作,那必然有synchronized与之对应
}

再来看sychronized是谁

public final synchronized void join(long millis)

成员方法加了synchronized说明是synchronized(this)......

this是谁啊?看吧 bThread.join(0); 那说明this就是b线程对象本身。

我擦了个擦,a线程要骂了,tm在我身体里等b线程。

大家都知道,有了wait,必然有notify,我刚保证楼主在整个jdk里面都不会找到对b线程对象的notify操作。这就要看jvm代码了:

//一个c++函数:
void JavaThread::exit(bool destroy_vm, ExitType exit_type) 

//这家伙是啥,就是一个线程执行完毕之后,jvm会做的事,做清理啊收尾工作,
//里面有一个贼不起眼的一行代码,眼神不好还看不到的呢,就是这个:

ensure_join(this);

//翻译成中文叫 确保_join(这个);代码如下:

static void ensure_join(JavaThread* thread) {
  Handle threadObj(thread, thread->threadObj());

  ObjectLocker lock(threadObj, thread);

  thread->clear_pending_exception();

  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);

  java_lang_Thread::set_thread(threadObj(), NULL);

  //同志们看到了没,别的不用看,就看这一句,妈了个淡淡,
//thread就是当前线程,是啥是啥?就是刚才说的b线程啊。
  lock.notify_all(thread);

  thread->clear_pending_exception();
}

至此,b线程对象被notifyall了,那么a线程也就能继续跑下去了。

至于wait/notify是怎么实现的,其实jvm实现的方法和java里面的ReentrantLock原理差不多,都是各种waitinglist,各种status判断,各种cas操作,有兴趣可以看ReentrantLock源码。