5_关于Thread的join方法

  • 在Thread类中一共有__3种__join函数的重载形式,都是非静态函数

      public final void join() throws InterruptedException;
    
      public final synchronized void join(long millis) throws InterruptedException
    
      public final synchronized void join(long millis, int nanos) throws InterruptedException
    

    (其实它们仨的根源函数都是第二种形式)

  • 第二种形式的源码

      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);            //持有的是被等待线程t的锁, 那么被什么notify()或interrupt呢?
              }
          } else {
              while (isAlive()) {
                  long delay = millis - now;
                  if (delay <= 0) {
                      break;
                  }
                  wait(delay);
                  now = System.currentTimeMillis() - base;
              }
          }
      }
    
  • join函数的__作用__是:调用join函数的线程会进入等待状态(它等待的正是使用了join方法的线程实例,例如 在主线程中调用eatThread.join(), 那么主线程就会等待eatThread结束,才能再次重新运行状态或就绪状态)

  • 带参数的join方法,代表当前线程只等待另一个线程 xx毫秒,然后它就又恢复到运行状态或就绪状态了;

    不带参数的join方法,代表当前线程只能一直等,知道另一个线程完全结束才能恢复到运行状态或就绪状态

  • 示例

      class MyRunnable implements Runnable{
    
          @Override
          public void run() {
    
              System.out.println("Thread started::"+Thread.currentThread().getName());
    
              try {
                  Thread.sleep(40000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
    
              System.out.println("Thread ended::"+Thread.currentThread().getName());
          }
      }
    
    
      class ThreadJoinExample {
    
          public static void main(String[] args) {
    
              Thread t1 = new Thread(new MyRunnable(), "t1");
              Thread t2 = new Thread(new MyRunnable(), "t2");
              Thread t3 = new Thread(new MyRunnable(), "t3");
    
              t1.start();
    
              //start second thread after waiting for 20 seconds or if it's dead
              try {
                  t1.join(20000);
    
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
    
              t2.start();
    
              //start third thread only when first thread is dead
              try {
                  t1.join();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
    
              t3.start();
    
              //let all threads finish execution before finishing main thread
              try {
                  t1.join();
                  t2.join();
                  t3.join();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
    
              System.out.println("All threads are dead, exiting main thread");
          }
      }
    

    这个示例的结果是

      Thread started::t1  ---间隔大概20秒-->
      Thread started::t2  ---间隔大概20秒-->
      Thread ended::t1    ---几乎无间隔-->
      Thread started::t3  ---间隔大概20秒-->
      Thread ended::t2    ---间隔大概20秒-->
      Thread ended::t3    ---几乎无间隔-->
      All threads are dead, exiting main thread
    

    说明

    1° 在执行 t1.start()之前,程序只有一个主线程

    2° 执行 t1.start()后,很快 t1线程开始,输出Thread started::t1,然后开始长达40秒的sleep

    3° t1线程开始sleep以后,主线程继续向下执行,执行到t1.join(20000)时,代表主线程必须要等待20秒后或t1线程结束后,才能继续向下执行

    4° 20秒过去了,t1线程没有结束,此时它已经睡了20秒,主线程的等待时间过去了,它可以继续向下执行 t2.start(),很快t2线程开始,输出Thread started::t2,然后也开始长达40秒的sleep

    5° 现在t1和t2都在sleep,因此又会执行主线程,执行到t1.join()时,代表主线程只能等待t1结束才能向下执行

    6° 由于在4°时t1线程已经睡了20秒,因此它又睡了20秒后,会输出Thread ended::t1,线程t1结束

    7° 线程t1结束使得主线程可以继续向下执行,执行到t3.start()时,很快t3线程开始,输出Thread started::t3,然后也开始长达40秒的sleep

    8° 现在的情况是,线程t2还要再睡20秒(因为有20秒的时间是和t1一起睡的),线程t3还要睡40秒,因此又到了主线程,主线程向下执行t1.join(),但由于t1线程已经结束,所以继续向下执行;主线程执行t2.join(),此时要等t2结束才能向下执行

    9° 又过了大概20秒,t2线程睡醒,输出Thread ended::t2,线程t2结束,主线程可以向下执行t3.join(),等待t3线程结束

    10° 又过了大概20秒,t3线程睡醒,输出Thread ended::t3,线程t3结束,主线程可以向下执行System.out.println(“All threads are dead, exiting main thread”),输出All threads are dead, exiting main thread。此时主线程也执行完毕,程序退出

猜你喜欢

转载自blog.csdn.net/captxb/article/details/87598616