为什么80%的码农都做不了架构师?>>>   

thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

t.join();      //使调用线程 t 在此之前执行完毕。
t.join(1000);  //等待 t 线程,等待时间是1000毫秒

先上一段JDK中代码:

Java代码  

  1. /**

  2. *  Waits at most <code>millis</code> milliseconds for this thread to

  3. * die. A timeout of <code>0</code> means to wait forever.

  4. */

  5. //此处A timeout of 0 means to wait forever 字面意思是永远等待,其实是等到t结束后。

  6. public final synchronized void join(long millis)    throws InterruptedException {

  7. long base = System.currentTimeMillis();

  8. long now = 0;

  9. if (millis < 0) {

  10. throw new IllegalArgumentException("timeout value is negative");

  11. }

  12. if (millis == 0) {

  13. while (isAlive()) {

  14. wait(0);

  15. }

  16. } else {

  17. while (isAlive()) {

  18. long delay = millis - now;

  19. if (delay <= 0) {

  20. break;

  21. }

  22. wait(delay);

  23. now = System.currentTimeMillis() - base;

  24. }

  25. }

  26. }

从代码上看,如果线程被生成了,但还未被起动,调用它的join()方法是没有作用的,将直接继续向下执行

Join方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁

Example1:

Java代码  

  1. public class JoinTest implements Runnable{

  2. public static int a = 0;

  3. public void run() {

  4. for (int k = 0; k < 5; k++) {

  5. a = a + 1;

  6. }

  7. }

  8. public static void main(String[] args) throws Exception {

  9. Runnable r = new JoinTest();

  10. Thread t = new Thread(r);

  11. t.start();

  12. System.out.println(a);

  13. }

  14. }

请 问程序的输出结果是5吗?答案是:有可能。其实你很难遇到输出5的时候,通常情况下都不是5。当然这也和机器有严重的关系。为什么呢?我的解释是当 主线程 main方法执行System.out.println(a);这条语句时,线程还没有真正开始运行,或许正在为它分配资源准备运行。因为为线程分配资源 需要时间,而main方法执行完t.start()方法后继续往下执行System.out.println(a);,这个时候得到的结果是a还没有被 改变的值0。怎样才能让输出结果为5!其实很简单,join() 方法提供了这种功能。join() 方法,它能够使调用该方法的线程在此之前执行完毕。

Java代码  

  1. public static void main(String[] args) throws Exception {

  2. Runnable r = new JoinTest();

  3. Thread t = new Thread(r);

  4. t.start();

  5. t.join(); //加入join()

  6. System.out.println(a);

  7. }

这个时候,程序输入结果始终为5。

为 了证明如果不使用t.join()方法,主线程main方法的System.out.println(a);语句将抢先执行,我们可以在main方法中加 入一个循环,这个循环用来延长main方法执行的时间,循环次数将严重取决于机器性能。如果循环次数得当,我们也可以看到a的输出结果是5。

Java代码  

  1. public static void main(String[] args) throws Exception {

  2. Runnable r = new JoinTest();

  3. Thread t = new Thread(r);

  4. t.start();

  5. //t.join(); //加入join()

  6. /*

  7. 注意循环体内一定要有实际执行语句,否则编译器或JVM可能优化掉你的这段代码,视这段代

  8. 码为无效。

  9. */

  10. for (int i=0; i<300; i++) {

  11. System.out.print(i);

  12. }

  13. System.out.println();

  14. System.out.println(a);

  15. }

经自己测试,最后a一直是5.

本例参考:http://agio.iteye.com/blog/210600

Example2:join(n)

Java代码  

  1. class RunnableImpl implements Runnable {

  2. public void run() {

  3. try {

  4. System.out.println("Begin sleep");

  5. Thread.sleep(1000);

  6. System.out.println("End sleep");

  7. } catch (InterruptedException e) {

  8. e.printStackTrace();

  9. }

  10. }

  11. }

Java代码  

  1. public class JoinTest{

  2. public static void main(String[] args) {

  3. Thread t = new Thread(new RunnableImpl());

  4. t.start();

  5. try {

  6. t.join(1000);

  7. System.out.println("joinFinish");

  8. } catch (InterruptedException e) {

  9. e.printStackTrace();

  10. }

  11. }

  12. }

结果是:
Begin sleep
End sleep
joinFinish

明白了吧,当main线程调用t.join时,main线程等待t线程,等待时间是1000,如果t线程Sleep 2000呢

Java代码  

  1. class RunnableImpl implements Runnable {

  2. public void run() {

  3. try {

  4. System.out.println("Begin sleep");

  5. Thread.sleep(2000); //原来为1000

  6. System.out.println("End sleep");

  7. } catch (InterruptedException e) {

  8. e.printStackTrace();

  9. }

  10. }

  11. }

结果是:
Begin sleep
joinFinish
End sleep
也就是说main线程只等1000毫秒,不管T什么时候结束.

参考:http://blog.csdn.net/FG2006/archive/2011/05/04/6393768.aspx

Example3:

Java代码  

  1. class CustomThread1 extends Thread {

  2. public void run() {

  3. String threadName = Thread.currentThread().getName();

  4. System.out.println(threadName + " start.");

  5. try {

  6. for (int i = 0; i < 5; i++) {

  7. System.out.println(threadName + " loop at " + i);

  8. Thread.sleep(1000);

  9. }

  10. System.out.println(threadName + " end.");

  11. } catch (Exception e) {

  12. System.out.println("Exception from " + threadName + ".run");

  13. }

  14. }

  15. }

  16. class CustomThread extends Thread {

  17. CustomThread1 t1;

  18. public CustomThread(CustomThread1 t1) {

  19. this.t1 = t1;

  20. }

  21. public void run() {

  22. String threadName = Thread.currentThread().getName();

  23. System.out.println(threadName + " start.");

  24. try {

  25. t1.join();

  26. System.out.println(threadName + " end.");

  27. } catch (Exception e) {

  28. System.out.println("Exception from " + threadName + ".run");

  29. }

  30. }

  31. }

  32. public class JoinTestDemo {

  33. public static void main(String[] args) {

  34. String threadName = Thread.currentThread().getName();

  35. System.out.println(threadName + " start.");

  36. CustomThread1 t1 = new CustomThread1();

  37. CustomThread t = new CustomThread(t1);

  38. try {

  39. t1.start();

  40. Thread.sleep(2000);

  41. t.start();

  42. t.join(); //在代碼2里,將此處注釋掉

  43. } catch (Exception e) {

  44. System.out.println("Exception from main");

  45. }

  46. System.out.println(threadName + " end!");

  47. }

  48. }

结果:

main start.    //main方法所在的线程起动,但没有马上结束,因为调用t.join();,所以要等到t结束了,此线程才能向下执行。

[CustomThread1] Thread start.     //线程CustomThread1起动
[CustomThread1] Thread loop at 0  //线程CustomThread1执行
[CustomThread1] Thread loop at 1  //线程CustomThread1执行
[CustomThread] Thread start.      //线程CustomThread起动,但没有马上结束,因为调用t1.join();,所以要等到t1结束了,此线程才能向下执行。
[CustomThread1] Thread loop at 2  //线程CustomThread1继续执行
[CustomThread1] Thread loop at 3  //线程CustomThread1继续执行
[CustomThread1] Thread loop at 4  //线程CustomThread1继续执行
[CustomThread1] Thread end.       //线程CustomThread1结束了
[CustomThread] Thread end.        // 线程CustomThread在t1.join();阻塞处起动,向下继续执行的结果

main end!      //线程CustomThread结束,此线程在t.join();阻塞处起动,向下继续执行的结果。

将上例中的join注释掉:

Java代码  

  1. public class JoinTestDemo {

  2. public static void main(String[] args) {

  3. String threadName = Thread.currentThread().getName();

  4. System.out.println(threadName + " start.");

  5. CustomThread1 t1 = new CustomThread1();

  6. CustomThread t = new CustomThread(t1);

  7. try {

  8. t1.start();

  9. Thread.sleep(2000);

  10. t.start();

  11. //t.join();

  12. } catch (Exception e) {

  13. System.out.println("Exception from main");

  14. }

  15. System.out.println(threadName + " end!");

  16. }

  17. }

结果:

main start. // main方法所在的线程起动,但没有马上结束,这里并不是因为join方法,而是因为Thread.sleep(2000);

[CustomThread1] Thread start.      //线程CustomThread1起动
[CustomThread1] Thread loop at 0   //线程CustomThread1执行
[CustomThread1] Thread loop at 1   //线程CustomThread1执行
main end!   // Thread.sleep(2000);结束,虽然在线程CustomThread执行了t1.join();,但这并不会影响到其他线程(这里main方法所在的线程)。
[CustomThread] Thread start.       //线程CustomThread起动,但没有马上结束,因为调用t1.join();,所以要等到t1结束了,此线程才能向下执行。
[CustomThread1] Thread loop at 2   //线程CustomThread1继续执行
[CustomThread1] Thread loop at 3   //线程CustomThread1继续执行
[CustomThread1] Thread loop at 4   //线程CustomThread1继续执行
[CustomThread1] Thread end.       //线程CustomThread1结束了
[CustomThread] Thread end.        // 线程CustomThread在t1.join();阻塞处起动,向下继续执行的结果

本例参考:http://blog.csdn.net/bzwm/archive/2009/02/12/3881392.aspx

Example4:

main 线程调用t.join时,必须能够拿到线程t对象的锁,如果拿不到它是无法wait的,刚开的例子t.join(1000)不是说明了main线程等待1 秒,如果在它等待之前,其他线程获取了t对象的锁,它等待时间可不就是1毫秒了。

Java代码  

  1. class RunnableImpl implements Runnable {

  2. public void run() {

  3. try {

  4. System.out.println("Begin sleep");

  5. Thread.sleep(2000);

  6. System.out.println("End sleep");

  7. } catch (InterruptedException e) {

  8. e.printStackTrace();

  9. }

  10. }

  11. }

Java代码  

  1. class ThreadTest extends Thread {

  2. Thread thread;

  3. public ThreadTest(Thread thread) {

  4. this.thread = thread;

  5. }

  6. @Override

  7. public void run() {

  8. synchronized (thread) {

  9. System.out.println("getObjectLock");

  10. try {

  11. Thread.sleep(9000);

  12. } catch (InterruptedException ex) {

  13. ex.printStackTrace();

  14. }

  15. System.out.println("ReleaseObjectLock");

  16. }

  17. }

  18. }

Java代码  

  1. public class JoinTest {

  2. public static void main(String[] args) {

  3. Thread t = new Thread(new RunnableImpl());

  4. new ThreadTest(t).start();

  5. t.start();

  6. try {

  7. t.join();

  8. System.out.println("joinFinish");

  9. } catch (InterruptedException e) {

  10. e.printStackTrace();

  11. }

  12. }

  13. }

结果:
getObjectLock
Begin sleep
End sleep
ReleaseObjectLock
joinFinish

在main方法中 通过new ThreadTest(t).start()实例化ThreadTest 线程对象, 它通过 synchronized (thread),获取线程对象t的锁,并Sleep(9000)后释放,这就意味着,即使main方法t.join(1000)等待一秒钟,它必须等待ThreadTest 线程释放t锁后才能进入wait方法中,它实际等待时间是9000+1000ms。

例子参考Example2来源.

转载于:https://my.oschina.net/kepler/blog/208027

Join()--用法相关推荐

  1. linux线程join的用法,join用法

    Join用法 - a 1显示第一个文件的不匹配行,- a 2为从第二个文件中显示不匹配行. n.m    n为文件号,m为域号.1 . 3表示只显示文件1第三域,每个n,m必须用逗号分隔,如1 . 3 ...

  2. Java线程中wait、await、sleep、yield、join用法总结

    文章目录 一.wait().notify().notifyAll()用法 二.await().signal().signalAll()用法 三 .yield().join()用法 四.wait().a ...

  3. boost::fusion::join用法的测试程序

    boost::fusion::join用法的测试程序 实现功能 C++实现代码 实现功能 boost::fusion::join用法的测试程序 C++实现代码 #include <boost/d ...

  4. SQL中的left outer join,inner join,right outer join用法 (左右内连接)

    SQL语句中的left outer join,inner join,right outer join用法 left outer join=left join ,   right outer join= ...

  5. wait放弃对象锁_Java线程中wait、await、sleep、yield、join用法总结

    一.wait().notify().notifyAll()用法 obj.wait()/obj.wait(long timeout)是Object中的方法,当线程调用wait()方法,当前线程释放对象锁 ...

  6. oracle中何时会用到join,Oracle中join用法的演示

    以下的文章主要介绍的是Oracle中join用法,如果你是其方面的新手,对Oracle中oin的实际用法很感兴趣,但是却找不到一些资料去对其进行更深入的了解的话,你不妨浏览以下的文章对其进行了解. O ...

  7. thinkphp中join用法

    JOIN方法也是连贯操作方法之一,用于根据两个或多个表中的列之间的关系,从这些表中查询数据. 附上项目中的left join用法的代码: 1 $data = M("groups g" ...

  8. Oracle的join默认为,oracle join用法

    文章分类:数据库 join用法 条件连接(join) T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON boolean_expre ...

  9. mysql 联表比对,MySQL联表查询详解/超详细mysql left join,right join,inner join用法分析比较...

    超详细mysql left join,right join,inner join用法分析 下面是例子分析 表A记录如下: aID aNum 1 a20050111 2 a20050112 3 a200 ...

  10. 多线程之join用法

    先看例子: 网上的例子 /** * join的用法,哪个线程调用join哪个线程就插队先执行 */ public class JoinTest {public static void main(Str ...

最新文章

  1. linux i2c 读写函数,Linux下读写芯片的I2C寄存器
  2. Appium 与 Chromedriver
  3. GoldenGate 基本参数含义
  4. WinXP——如何重装XP系统
  5. Linux内核邮件列表发送和回复格式研究
  6. oracle 自动关闭 数据库连接
  7. Python图片文字识别——Windows下Tesseract-OCR的安装与使用
  8. 【作业报告】作业5 四则运算 测试与封装 5.2(已更新)
  9. Qt 判断集合中的元素是否全部相同
  10. 蜂鸣器驱动电路 自主开发设计
  11. 开学必备宿舍神器,续航好的蓝牙耳机推荐
  12. 数学分析(1):集合相关公式的证明
  13. 息屏录像软件下载地址和教程
  14. unity3d 连接mysql_我学院:Unity3D连接MySql数据库的方法
  15. zzuli OJ 2331:小新同学的智商
  16. 网上作业提交系统的数据库表
  17. ubuntu写yacc
  18. GIS教程之 在 React 中创建 Openlayers 地图(教程含源码)
  19. 机器学习编译器的前世今生
  20. android 调用搜狗地图api,sogou地图API用法实例教程

热门文章

  1. Java关于继承中的内存分配
  2. zabbix重点笔记
  3. Volley(五)—— 自定义Request
  4. 洛谷OJ P1074 靶形数独 解题报告
  5. SharePoint 2013 母版页修改后,无法添加应用程序
  6. Unbuntu学习笔记之安装vmware tools
  7. linux下赋予普通用户管理员权限
  8. 第k小元素——分治法
  9. Linux环境安装PostgreSQL-12.2
  10. Android真机调试时LogCat不显示日志信息