浅谈Java线程Thread.join方法解析
join字面上是加入的意思,我们先看看join方法的解释和实现。
/** *Waitsforthisthreadtodie. *调用方线程(调用join方法的线程)执行等待操作,直到被调用的线程(join方法所属的线程)结束,再被唤醒 *Aninvocationofthismethodbehavesinexactlythesame *wayastheinvocation * * *@throwsInterruptedException *ifanythreadhasinterruptedthecurrentthread.The *interruptedstatusofthecurrentthreadis *clearedwhenthisexceptionisthrown. */ publicfinalvoidjoin()throwsInterruptedException{ join(0); }
这里join是调用的
/** *Waitsatmost{@codemillis}millisecondsforthisthreadto *die.Atimeoutof{@code0}meanstowaitforever. *等待线程执行结束,或者指定的最大等待时间到了,调用方线程再次被唤醒,如果最大等待时间为0,则只能等线程执行结束,才能被唤醒。 *Thisimplementationusesaloopof{@codethis.wait}calls *conditionedon{@codethis.isAlive}.Asathreadterminatesthe *{@codethis.notifyAll}methodisinvoked.Itisrecommendedthat *applicationsnotuse{@codewait},{@codenotify},or *{@codenotifyAll}on{@codeThread}instances. * * */ publicfinalsynchronizedvoidjoin(longmillis) throwsInterruptedException{ longbase=System.currentTimeMillis(); longnow=0; if(millis<0){ thrownewIllegalArgumentException("timeoutvalueisnegative"); } if(millis==0){ while(isAlive()){ wait(0); } }else{ while(isAlive()){ longdelay=millis-now; if(delay<=0){ break; } wait(delay); now=System.currentTimeMillis()-base; } } }
可以看到,join方法本身是通过wait方法来实现等待的,这里判断如果线程还在运行中的话,则继续等待,如果指定时间到了,或者线程运行完成了,则代码继续向下执行,调用线程就可以执行后面的逻辑了。
但是在这里没有看到哪里调用notify或者notifyAll方法,如果没有调用的话,那调用方线程会一直等待下去,那是哪里调用了唤醒它的方法呢?通过查证得知,原来在线程结束时,java虚拟机会执行该线程的本地exit方法,
//线程退出函数: voidJavaThread::exit(booldestroy_vm,ExitTypeexit_type){ ... //这里会处理join相关的销毁逻辑 ensure_join(this); ... } //处理join相关的销毁逻辑 staticvoidensure_join(JavaThread*thread){ HandlethreadObj(thread,thread->threadObj()); ObjectLockerlock(threadObj,thread); thread->clear_pending_exception(); 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(); }
这样线程什么时候被唤醒就明白了。下面写个例子看下效果。
publicclassJoinTest{ publicstaticvoidmain(String[]args){ ThreadBoyboy=newThreadBoy(); boy.start(); } staticclassThreadBoyextendsThread{ @Override publicvoidrun(){ System.out.println("男孩和女孩准备出去逛街"); ThreadGirlgirl=newThreadGirl(); girl.start(); try{ girl.join(); }catch(InterruptedExceptione){ e.printStackTrace(); } System.out.println("男孩和女孩开始去逛街了"); } } staticclassThreadGirlextendsThread{ @Override publicvoidrun(){ inttime=5000; System.out.println("女孩开始化妆,男孩在等待。。。"); try{ Thread.sleep(time); }catch(InterruptedExceptione){ e.printStackTrace(); } System.out.println("女孩化妆完成!,耗时"+time); } } }
执行结果为:
男孩和女孩准备出去逛街
女孩开始化妆,男孩在等待。。。
女孩化妆完成!,耗时5000
男孩和女孩开始去逛街了
就是男孩和女孩准备去逛街,女孩要化妆先,等女孩化妆完成了,再一起去逛街。
那join(time)的用法是怎么样的呢?
publicclassJoinTest{ publicstaticvoidmain(String[]args){ ThreadBoyboy=newThreadBoy(); boy.start(); } staticclassThreadBoyextendsThread{ @Override publicvoidrun(){ System.out.println("男孩和女孩准备出去逛街"); ThreadGirlgirl=newThreadGirl(); girl.start(); inttime=2000; try{ girl.join(time); }catch(InterruptedExceptione){ e.printStackTrace(); } System.out.println("男孩等了"+time+",不想再等了,去逛街了"); } } staticclassThreadGirlextendsThread{ @Override publicvoidrun(){ inttime=5000; System.out.println("女孩开始化妆,男孩在等待。。。"); try{ Thread.sleep(time); }catch(InterruptedExceptione){ e.printStackTrace(); } System.out.println("女孩化妆完成!,耗时"+time); } } }
这里仅仅把join方法换成了join(time)方法,描述改了点,打印的结果是:
男孩和女孩准备出去逛街
女孩开始化妆,男孩在等待。。。
男孩等了2000,不想再等了,去逛街了
女孩化妆完成!,耗时5000
男孩等了join(time)中的time时间,如果这个time时间到达之后,女孩所在的线程还没执行完,则不等待了,继续执行后面的逻辑,就是不等女孩了,自己去逛街。
由此看出,join方法是为了比较方便的实现两个线程的同步执行,线程1执行,碰到线程2后,等待线程2执行后,再继续执行线程1的执行,加入的意思现在就比较形象化了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。