黑马程序员技术交流社区

标题: Thread的join()方法 疑惑 [打印本页]

作者: 崔朋朋    时间: 2012-9-6 12:26
标题: Thread的join()方法 疑惑
本帖最后由 崔朋朋 于 2012-9-9 17:15 编辑

现在有 线程a 和 线程b     
线程b的run()方法如下:
run(){
...
a.join();
...
}

问题:
当执行完a.join();后是线程a“加入"到b的尾部?还是线程b"加入"到a的尾部?
接下来是执行线程b的run方法?还是执行线程a的run方法?
作者: 袁艳超    时间: 2012-9-6 13:06
楼上说反了吧,当执行到a.join()时,b线程停止,执行线程a的run方法
作者: 袁艳超    时间: 2012-9-6 13:24
首先要使用join方法,得有两个以上的线程,如果就一个线程,它调用自己的join方法阻塞自己,没有意义!
假如连个线程A和线程B
那么肯定是线程A里调用了B线程的join方法,或者线程B里调用了A线程的join方法
如果是A线程调用B线程的join方法的话,那就是这样的:
class A extends Thread{
public void run(){
  ...
  new B().join();  //查看API( join方法的解释是:--等待该线程终止。),这句话的意思就是:B线程调用join方法,那么就等待B线程终止,也就是等着B执行完
}
}

作者: 杨锦    时间: 2012-9-6 13:46
当前线程暂停,等待加入的线程运行结束,当前线程继续执行。
是b线程暂停,等a线程运行完之后,b线程继续执行
class Test {

public static void main(String[] args) {
  final Thread t1 = new Thread(){
   public void run() {
    for (int i = 1; i <= 5; i++) {
     System.out.println("A " + i);
     try {
      Thread.sleep(1000);   
     } catch(Exception e) {
      e.printStackTrace();
     }
    }
   }
  };
  
  Thread t2 = new Thread(){
   public void run() {
    for (int i = 1; i <= 5; i++) {
     System.out.println("B " + i);
     try {
      Thread.sleep(1000);   
      if (i == 2)
       t1.join();   // 当前线程暂停, 等待t1线程执行结束之后再继续
     } catch(Exception e) {
      e.printStackTrace();
     }
    }
   }
  };
  
  t1.start();
  t2.start();
}

}

作者: 崔朋朋    时间: 2012-9-6 19:37
杨锦 发表于 2012-9-6 13:46
当前线程暂停,等待加入的线程运行结束,当前线程继续执行。
是b线程暂停,等a线程运行完之后,b线程继续执 ...

嗯   明白
a.join();   执行完毕后.   
执行join()线程的run()方法,join线程的run()方法执行完毕后,在执行当前线程
:handshake
作者: AngieFans85    时间: 2012-9-6 19:49
当b线程执行到a.join();时,b线程就会暂时停止运行,此时就执行a线程中的run()方法.必须要等到a线程彻底彻底执行结束时(也就是说a线程的run()方法的代码执行到末尾),b线程才可以继续执行.当a线程结束后,a线程就不存在了,a线程所占用的空间就被释放了,所以不存在"谁加入谁尾部"的说法.
作者: 任艳旭    时间: 2012-9-7 14:39
本帖最后由 任艳旭 于 2012-9-7 14:51 编辑

执行a.join()方法,当前线程暂停,也就是线程b,这时候开始运行线程a,执行线程a的run()方法体。线程a的run()方法运行完后,线程b接着运行,向下执行语句。
举个例子:
下面创建两个线程
class ThreadDemo {
        
        public static void main(String[] args) {
                final Thread t1 = new Thread(){
                        public void run() {
                                for (int i = 1; i <= 5; i++) {
                                        System.out.println("A " + i);
                                        try {
                                                Thread.sleep(1000);  //线程t1休眠一秒,线程t2开始      
                                        } catch(Exception e) {
                                                e.printStackTrace();        
                                        }
                                }
                        }        
                };
               
                Thread t2 = new Thread(){
                        public void run() {
                                for (int i = 1; i <= 5; i++) {
                                        System.out.println("B " + i);
                                        try {
                                                Thread.sleep(1000);                //线程t2开始休眠                     
                                                if (i == 2)                              //判断如果i=2的时候,那么就执行下面一句
                                                        t1.join();                        // 当前线程暂停, 等待t1线程执行结束之后再继续
                                        } catch(Exception e) {
                                                e.printStackTrace();        
                                        }
                                }
                        }        
                };
               
                t1.start();
                t2.start();
        }        
        
}
运行结果是这样的:
A 1
B 1
B 2
A 2
A 3
A 4
A 5
B 3
B 4
B 5

作者: 陈振兴    时间: 2012-9-9 03:29
本帖最后由 陈振兴 于 2012-9-9 03:39 编辑

来个最简单的例子:也是我那个提交测试题当中的
/**
* 模拟妈妈做饭,做饭时发现没有盐了,让儿子去买盐(假设买盐需要3分钟),只有盐买回来之后,妈妈才能继续做饭的过程。
* @author xinglefly
* @version 1
*/
class Mother implements Runnable{
        public void run(){
                System.out.println("妈妈准备做午饭了");
                System.out.println("妈妈发现盐用完了,让儿子去买盐");
                //创建儿子的线程
                Thread son = new Thread(new Son());
                //开启线程
                son.start();
                System.out.println("妈妈等儿子回来");
                try{
                        //等待线程终止
                        son.join();
                }catch(InterruptedException e){
                        //标准错误输出流
                        System.err.print("儿子出事了");
                        System.err.print("妈妈做饭中断");
                        //非0状态异常终止java虚拟机
                        System.exit(1);
                }
                System.out.println("妈妈开始做饭");
                System.out.println("妈妈煮好了饭");
        }
}
class Son implements Runnable{
        public void run(){
                System.out.println("儿子出去买盐");
                System.out.println("买盐需要3分钟");
                try{
                        for(int i=0;i<=3;i++){
                                Thread.sleep(1000*60*3);
                                System.out.println(i+"分钟");
                        }
                }catch(InterruptedException e){
                        System.out.println("儿子发生意外");
                }
                System.out.println("儿子买盐完事");
        }
}
public class Test10 {

        public static void main(String[] args){
                new Thread(new Mother()).start();
        }
}
这样对join的印象会更深刻!执行的顺序就是这样!你在看楼上的文字叙述会舒服很多!






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2