前言:
现时看官们对“vbnetthreadjoin”大致比较注意,同学们都需要学习一些“vbnetthreadjoin”的相关知识。那么小编同时在网摘上搜集了一些对于“vbnetthreadjoin””的相关知识,希望看官们能喜欢,姐妹们快快来了解一下吧!Thread类中的join方法,用于等待某个线程执行结束。
简单示例
以下简单的代码,会让主线程等待子线程执行结束再执行。如果去掉t.join(),可能主线程就直接退出了,子线程都来不及执行。
package com.qcy.testJoin;/** * @author qcy * @create 2020/09/10 17:17:03 */public class Main { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } }); t.start(); t.join(); }}join源码分析
t.join()源码如下:
public final void join() throws InterruptedException { join(0); }
接着是调用join的单参数重载方法,传入等待时间0,表示一直等待下去
这一点也可以从重载方法的注释中看到
单参数的重载方法如下:以主线程调用t.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) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
(1)由于这里出现了synchronized,因此主线程需要拿到子线程对象t的锁。
(2)当millis为0的时候,循环判断isAlive(),即判断线程是否存活,如果存活,调用子线程对象的wait方法,传入0也是表示一直等待下去
/** * Tests if this thread is alive. A thread is alive if it has * been started and has not yet died. * * @return <code>true</code> if this thread is alive; * <code>false</code> otherwise. */ public final native boolean isAlive();
(3)当主线程调用子线程对象的wait方法后,主线程释放掉锁,并进入等待状态。
(4)当子线程运行结束,不再是存活状态,那么主线程需要被唤醒,且需要再次获取到锁,才能继续运行join剩余的方法,运行结束后,主线程从join方法中返回,继续运行main剩余的方法。
JVM底层代码分析
问题来了,主线程什么时候被唤醒?唤醒代码又是在哪里的呢?
这要看jvm的底层代码,在thread.cpp代码中,地址thread.cpp地址
在线程退出的代码中,调用了ensure_join()方法
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); .... // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this);}
从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();}
java_lang_Thread::set_thread(threadObj(), NULL)语句,由上面的注释,可以了解到该方法会清除本地线程实例,将会使得isAlive()返回false,接着在调用完lock.notify_all(thread)语句后,即通知在此线程对象上的等待者,我们例子中的主线程在重新获得CPU分配的时间片后,会直接从join方法中返回。
其他方式
至此,我们了解到了join方法的原理,不过join我们很少用到,在主线程等待子线程执行结束再执行的场景下,有更好更优雅的方法,可以参考我的另外一篇博客面试官:如何让主线程等待所有的子线程执行结束之后再执行?我懵了
标签: #vbnetthreadjoin