一 体系化深入学习并发编程由简入繁系统梳理并发知识点( 九 )


打印结果如下:
join前主线程状态:RUNNABLEjoin期间主线程状态:WAITINGjoin后主线程状态:RUNNABLE
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;}}}
它的核心是调用wait方法,分别是传入0时的wait方法(无线等待)和传入delay的wait方法(有限等待);
有限等待还好说,因为时间到了能够自动唤醒 。
而wait(0)却没有被看到有关方法的执行
其实是因为在JVM内部,线程执行完毕退出时,会执行一个唤醒线程的方法:lock.()
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 anywaythread->clear_pending_exception();// Thread is exiting. So set thread_status field injava.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 belowjava_lang_Thread::set_thread(threadObj(), NULL);lock.notify_all(thread);// Ignore pending exception (ThreadDeath), since we are exiting anywaythread->clear_pending_exception();}
所以,主线程调用.join()也可以等价于调用
synchronized(thread){thread.wait()}
因为主线程拿到的后,进入等待状态,而方法运行完成后,会自动唤醒拥有的的线程(主线程)
public static void main(String[] args) throws InterruptedException {Thread thread =new Thread(()->{System.out.println(Thread.currentThread().getName()+"开始运行");try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"结束运行");});thread.start();//thread.join();synchronized (thread){thread.wait();}System.out.println("主线程执行完毕");}
和join相似作用的还有JUC库中的和
通常我们应该用更成熟的包装类来达到效果 。
.yield()
它的作用是释放自己的CPU时间片
A hint to thethat theisto yield itsuse of a . Theis free tothis hint.
Yield is atothat wouldover- a CPU. Its usebewithandtothat ithas the.
不过官方也说了这个方法很少使用
It isto use this . It may beforor, where it may help tobugs due to race . It may also bewhensuch as the ones in the java.util..locks …
因为这个方法在JVM中不稳定,并不能确保运行,比如CPU资源很空闲,可能执行了该方法,也不会释放时间片,但该方法在JUC库中使用的比较多
yield执行后,仍然是状态,而不是,或者,因为它仅仅是让出自己的CPU资源,而不是让出锁资源
它和sleep方法有些类似
不过不同的是,sleep时,是不会得到CPU资源的分配的
而yield不一样,可能刚刚才让出了CPU资源,马上又立刻得到时间片
线程的重要属性 线程ID
每个线程有自己的id,就像key-value,通过id可以确定与之匹配的线程,是不允许被修改的
线程的ID是自增长的