淺談Java線程Thread.join方法解析,javathread.join

來源:互聯網
上載者:User

淺談Java線程Thread.join方法解析,javathread.join

join字面上是加入的意思,我們先看看join方法的解釋和實現。

/**   * Waits for this thread to die.   * 調用方線程(調用join方法的線程)執行等待操作,直到被調用的線程(join方法所屬的線程)結束,再被喚醒   * <p> An invocation of this method behaves in exactly the same   * way as the invocation   *   *   * @throws InterruptedException   *     if any thread has interrupted the current thread. The   *     <i>interrupted status</i> of the current thread is   *     cleared when this exception is thrown.   */  public final void join() throws InterruptedException {    join(0);  }

這裡join是調用的

/**   * Waits at most {@code millis} milliseconds for this thread to   * die. A timeout of {@code 0} means to wait forever.   * 等待線程執行結束,或者指定的最大等待時間到了,調用方線程再次被喚醒,如果最大等待時間為0,則只能等線程執行結束,才能被喚醒。   * <p> This implementation uses a loop of {@code this.wait} calls   * conditioned on {@code this.isAlive}. As a thread terminates the   * {@code this.notifyAll} method is invoked. It is recommended that   * applications not use {@code wait}, {@code notify}, or   * {@code notifyAll} on {@code Thread} instances.   *   *    */  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);      }    } else {      while (isAlive()) {        long delay = millis - now;        if (delay <= 0) {          break;        }        wait(delay);        now = System.currentTimeMillis() - base;      }    }  }

可以看到,join方法本身是通過wait方法來實現等待的,這裡判斷如果線程還在運行中的話,則繼續等待,如果指定時間到了,或者線程運行完成了,則代碼繼續向下執行,調用線程就可以執行後面的邏輯了。

但是在這裡沒有看到哪裡調用notify或者notifyAll方法,如果沒有調用的話,那調用方線程會一直等待下去,那是哪裡調用了喚醒它的方法呢?通過查證得知,原來線上程結束時,java虛擬機器會執行該線程的本地exit方法,

//線程退出函數:void JavaThread::exit(bool destroy_vm, ExitType exit_type) {...//這裡會處理join相關的銷毀邏輯ensure_join(this);...}//處理join相關的銷毀邏輯  static void ensure_join(JavaThread* thread) {   Handle threadObj(thread, thread->threadObj());   ObjectLocker lock(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();  }

這樣線程什麼時候被喚醒就明白了。下面寫個例子看下效果。

public class JoinTest {    public static void main(String[] args) {        ThreadBoy boy = new ThreadBoy();    boy.start();      }    static class ThreadBoy extends Thread{    @Override    public void run() {            System.out.println("男孩和女孩準備出去逛街");            ThreadGirl girl = new ThreadGirl();      girl.start();            try {        girl.join();      } catch (InterruptedException e) {        e.printStackTrace();      }            System.out.println("男孩和女孩開始去逛街了");    }  }    static class ThreadGirl extends Thread{    @Override    public void run() {      int time = 5000;            System.out.println("女孩開始化妝,男孩在等待。。。");            try {        Thread.sleep(time);      } catch (InterruptedException e) {        e.printStackTrace();      }            System.out.println("女孩化妝完成!,耗時" + time);          }  }  }

執行結果為:

男孩和女孩準備出去逛街
女孩開始化妝,男孩在等待。。。
女孩化妝完成!,耗時5000
男孩和女孩開始去逛街了

就是男孩和女孩準備去逛街,女孩要化妝先,等女孩化妝完成了,再一起去逛街。

那join(time)的用法是怎麼樣的呢?

public class JoinTest {    public static void main(String[] args) {        ThreadBoy boy = new ThreadBoy();    boy.start();      }    static class ThreadBoy extends Thread{    @Override    public void run() {            System.out.println("男孩和女孩準備出去逛街");            ThreadGirl girl = new ThreadGirl();      girl.start();            int time = 2000;      try {        girl.join(time);      } catch (InterruptedException e) {        e.printStackTrace();      }            System.out.println("男孩等了" + time + ", 不想再等了,去逛街了");    }  }    static class ThreadGirl extends Thread{    @Override    public void run() {      int time = 5000;            System.out.println("女孩開始化妝,男孩在等待。。。");            try {        Thread.sleep(time);      } catch (InterruptedException e) {        e.printStackTrace();      }            System.out.println("女孩化妝完成!,耗時" + time);          }  }  }

這裡僅僅把join方法換成了join(time)方法,描述改了點,列印的結果是:

男孩和女孩準備出去逛街
女孩開始化妝,男孩在等待。。。
男孩等了2000, 不想再等了,去逛街了
女孩化妝完成!,耗時5000

男孩等了join(time)中的time時間,如果這個time時間到達之後,女孩所在的線程還沒執行完,則不等待了,繼續執行後面的邏輯,就是不等女孩了,自己去逛街。

由此看出,join方法是為了比較方便的實現兩個線程的同步執行,線程1執行,碰到線程2後,等待線程2執行後,再繼續執行線程1的執行,加入的意思現在就比較形象化了。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.