java join()用法示例

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


作用:可以让我们在执行一个方法前,先执行另外一个方法,或者说,可以帮我们把一些并行执行的过程改为串行执行。

1.示例如下:

主线程执行一段时间后,需要先执行一个子线程里的任务,然后再执行主线程。
测试类

package com.java4all.controller;

/**
* Author: yunqing
* Date: 2018/7/31
* Description:
*/
public class Test1 {

public static void main(String[] args){
try {
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务前1");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务前2");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务前3");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务前4");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务前5");
MyThread myThread = new MyThread();
myThread.start();
myThread.join();
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务后1");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务后2");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务后3");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务后4");
System.out.println(Thread.currentThread().getName()+"======>主线程在执行任务后5");
}catch (Exception ex){
ex.printStackTrace();
}
}


}

子线程类

package com.java4all.controller;

/**
* Author: yunqing
* Date: 2018/7/31
* Description:
*/
public class MyThread extends Thread{
@Override
public void run() {
for(int i = 0; i < 20; i ++){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"======>子线程在执行任务:"+i);
}catch (Exception ex){
ex.printStackTrace();
}
}
}

}

执行结果为:

main======>主线程在执行任务前1
main======>主线程在执行任务前2
main======>主线程在执行任务前3
main======>主线程在执行任务前4
main======>主线程在执行任务前5
Thread-0======>子线程在执行任务:0
Thread-0======>子线程在执行任务:1
Thread-0======>子线程在执行任务:2
Thread-0======>子线程在执行任务:3
Thread-0======>子线程在执行任务:4
Thread-0======>子线程在执行任务:5
Thread-0======>子线程在执行任务:6
Thread-0======>子线程在执行任务:7
Thread-0======>子线程在执行任务:8
Thread-0======>子线程在执行任务:9
Thread-0======>子线程在执行任务:10
Thread-0======>子线程在执行任务:11
Thread-0======>子线程在执行任务:12
Thread-0======>子线程在执行任务:13
Thread-0======>子线程在执行任务:14
Thread-0======>子线程在执行任务:15
Thread-0======>子线程在执行任务:16
Thread-0======>子线程在执行任务:17
Thread-0======>子线程在执行任务:18
Thread-0======>子线程在执行任务:19
main======>主线程在执行任务后1
main======>主线程在执行任务后2
main======>主线程在执行任务后3
main======>主线程在执行任务后4
main======>主线程在执行任务后5

可以看到,主线程执行一段时间后,子线程调用了join()方法,此时主线程阻塞,直到子线程执行完毕,主线程才继续执行。

2.原理

我们查看一下Thread.join()方法的源码:

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;
}
}
}

其实是通过wait来实现的,当发现子线程还活着时,那主线程就一直等待。

3.另一种用法

当我们在join()方法中传入参数时,比如1000,那么主线程只会阻塞1000ms,然后就恢复了并行的执行状态。
如果我们把上面的代码改为:

myThread.join(1000);

那么结果为:

main======>主线程在执行任务前1
main======>主线程在执行任务前2
main======>主线程在执行任务前3
main======>主线程在执行任务前4
main======>主线程在执行任务前5
main======>主线程在执行任务后1
main======>主线程在执行任务后2
main======>主线程在执行任务后3
main======>主线程在执行任务后4
main======>主线程在执行任务后5
Thread-0======>子线程在执行任务:0
Thread-0======>子线程在执行任务:1
Thread-0======>子线程在执行任务:2
Thread-0======>子线程在执行任务:3
Thread-0======>子线程在执行任务:4
Thread-0======>子线程在执行任务:5
Thread-0======>子线程在执行任务:6
Thread-0======>子线程在执行任务:7
Thread-0======>子线程在执行任务:8
Thread-0======>子线程在执行任务:9
Thread-0======>子线程在执行任务:10
Thread-0======>子线程在执行任务:11
Thread-0======>子线程在执行任务:12
Thread-0======>子线程在执行任务:13
Thread-0======>子线程在执行任务:14
Thread-0======>子线程在执行任务:15
Thread-0======>子线程在执行任务:16
Thread-0======>子线程在执行任务:17
Thread-0======>子线程在执行任务:18
Thread-0======>子线程在执行任务:19


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java