Thread源码分析之join方法

join方法示例1

源码

import java.util.concurrent.TimeUnit;
public class JoinWaitTest {
 private static int a = 0;
 private static int b = 100;
 public static void main(String... args) throws InterruptedException{
 Thread t = new Thread(new WaitThread());
 t.start();
 t.join();
 System.out.println("I'm waiting for WaitThread end.");
 System.out.println("The result is " + (a + b));
 }
 static class WaitThread implements Runnable {
 @Override
 public void run() {
 try {
 for (int i = 1; i < 6; i++) {
 TimeUnit.SECONDS.sleep(1);
 a++;
 System.out.println(i);
 }
 } catch (InterruptedException e) {
 }
 }
 }
}

执行结果

1

2

3

4

5

I'm waiting for WaitThread end.

The result is 105

场景描述

在很多情况下,主线程生成并启动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

本例只是个示例,演示的就是上述的过程。

join方法示例2

源码

import java.util.concurrent.TimeUnit;
public class JoinTest {
 public static void main(String... args) throws InterruptedException {
 Thread jt = new Thread(new JoinThread());
 Thread tt = new Thread(new TimingThread());
 tt.start();
 tt.join();
 jt.start();
 }
 static class JoinThread implements Runnable {
 @Override
 public void run() {
 System.out.println("I have waited for too long.");
 }
 }
 static class TimingThread implements Runnable {
 @Override
 public void run() {
 for (int i = 0; i < 6; i++) {
 try {
 TimeUnit.SECONDS.sleep(1);
 System.out.println("Sleep end!");
 } catch (InterruptedException e) {
 }
 }
 }
 }
}

执行结果

Sleep end!

Sleep end!

Sleep end!

Sleep end!

Sleep end!

Sleep end!

I have waited for too long.

场景描述

跟源码示例1大同小异,只不过这次是jt线程要等待tt线程结束。

join方法源码分析

jdk源码

/**
 * Waits at most {@code millis} milliseconds for this thread to
 * die. A timeout of {@code 0} means to wait forever.
 *
 * <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.
 *
 * @param millis
 * the time to wait in milliseconds
 *
 * @throws IllegalArgumentException
 * if the value of {@code millis} is negative
 *
 * @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 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不带参数源码分析1--实质上是调用了wait方法

join()方法实质上就是join(0),最终执行代码如下所示

Thread源码分析之join方法

实质上调用代码1就相当于调用代码2

Thread源码分析之join方法

join带参数源码分析

核心代码

Thread源码分析之join方法

变一下:

while (isAlive()) {

if (millis <= now) {

break;

}

wait(millis - now);

now = System.currentTimeMillis() - base;

}

分析

base和now都是时间。base是刚执行代码时的时间,now是执行代码流逝的时间。判断mills时间是否流逝完毕,流逝完毕则break跳出代码。

相关推荐