前言:
眼前大家对“java jion方法”大概比较关切,看官们都想要学习一些“java jion方法”的相关知识。那么小编在网摘上搜集了一些对于“java jion方法””的相关内容,希望兄弟们能喜欢,同学们快快来了解一下吧!join() 方法的作用
在Java多线程中,没办法通过调配CPU执行时间,保证一个线程执行完成以后,另外一个再执行,要实现这个效果,可以通过join()方法来实现。
用线程的状态(详细的线程状态可以点击查看)来解释的话,A线程在执行B线程的join()或join(timeout)方法以后,A线程进入到WAITING或者TIMED_WAITING状态,一直等到B线程进入到TERMINATED状态或者A线程等待超时以后,A线程才会回到RUNNABLE状态。
简单的示例
废话不多说,先上个简单示例一起看一下:
public class SubThread extends Thread { @Override public void run() { System.out.println("子线程开始执行"); try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("子线程执行完成"); }}
public class MainThread { public static void main(String[] args) throws InterruptedException { System.out.println("主线程开始执行"); SubThread thread = new SubThread(); thread.start(); thread.join(); System.out.println("主线程执行完成"); }}
打印结果:
主线程开始执行子线程开始执行子线程执行完成主线程执行完成
不管执行几次,打印结果都是一致的,说明主线程确实要比等待了2秒的子线程还要晚执行结束。
实现原理
现在功能也了解了,示例也看过了,是时候分析一下join方法的原理。
public final void join() throws InterruptedException { join(0);}
join()方法内部调用了join(0)方法。
public final synchronized void join(long millis)throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; // 如果传入参数小于0,则直接抛出异常 if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { // 如果传入参数等于0,则无限等待 while (isAlive()) { wait(0); } } else { // 如果传入参数大于0,则会设置超时时间 while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } }}
从源码中我们可以看到,A线程调用了B线程的join方法,首先判断了B线程是否还存活,就是isAlive()方法,这个方法是一个native方法,如果B线程还是存活的,则调用wait()方法(点击了解wait()方法的作用)。因为while的存在,即便A线程被唤醒,除非isAlive()为false或者等待超时,不然会继续调用wait()方法。
但是这个有另外一个问题,我们知道wait方法是配合notify使用的,但是我们上面的示例里面并没有调用B线程的notify方法,那个A线程是什么时候被唤醒的呢?其实啊,在每一个线程退出的时候,都会调用一下notifyAll这个方法,我们一起来看一下C++的源码:
oid JavaThread::exit(booldestory_vm, ExitTypeexit_type);static void ensure_join(JavaThread*thread) { Handle threadObj(thread, thread -> threadObj()); ObjectLocker lock(threadObj, thread); thread -> clear_pending_exception(); // 修改为 TERMINATED 状态 java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED); java_lang_Thread::set_thread(threadObj(), NULL); //执行了notifyAll()操作 lock.notify_all(thread); thread -> clear_pending_exception();}最后的最后
join()方法有一个会导致死锁的问题,就是执行Thread.currentThread().join(),执行这个代码以后,相当于线程等待自己结束以后再执行,那肯定是没办法实现的嘛。我们也看一个小示例验证一下:
public class MainThread { public static void main(String[] args) throws InterruptedException { System.out.println("主线程开始执行"); Thread.currentThread().join(); System.out.println("主线程执行完成"); }}
主线程在执行完Thread.currentThread().join();后,再也不会结束了。因此我们在开发的时候一定警惕死锁问题,类似的,A线程调用B.join(),但是B线程又调用A.join(),也是妥妥的死锁。
标签: #java jion方法