join() ,与sleep()(不释放锁)、wait()(释放锁)方法都属于多线程运行控制常用方法。
join()的作用类似与排队,比如ThreadA调用了ThreadB的join()方法,则ThreadA会进入阻塞状态,ThreadB会一直运行,知道ThreadB结束后ThreadA才会继续执行。 场景比如,主线程需要等待子线程的运行结果进行汇总,如果主线程先于子线程运行完成,结果就会有误差,所以需要在主线程中调用子线程的join()方法,这样主线程就会等子线程运行完成后才会运行。类似的作用还有countDownLatch,countDownLatch还能灵活一点,能实现更复杂的业务场景。因为join是必须等待子线程运行完成后才会允许主线程执行,而countDownLatch子线程可以在任何阶段主动countDown。
下面举几个例子。
package join;
import lombok.extern.slf4j.Slf4j;
/**
* Description:
*
* @author: wulei
* Version: 1.0
* Create Date Time: 2019/11/16 10:36 AM.
* Update Date Time:
*/
@Slf4j
public class ThreadMain {
public static void main(String[] args) throws InterruptedException{
log.info("ThreadMain开始执行");
ThreadChild1 threadChild1 = new ThreadChild1();
threadChild1.start();
// 可以把join方法注释后观察结果
threadChild1.join();
log.info("ThreadMain执行完毕");
}
}
package join;
import lombok.extern.slf4j.Slf4j;
/**
* Description:
*
* @author: wulei
* Version: 1.0
* Create Date Time: 2019/11/16 10:51 AM.
* Update Date Time:
*/
@Slf4j
public class ThreadChild1 extends Thread {
@Override
public void run(){
int sleepTime = (int)(Math.random() * 1000);
try {
log.info("ThreadChild1准备执行");
Thread.sleep(sleepTime);
log.info("ThreadChild1执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
join()的源代码如下:
/** * 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()内部是使用wait()方法实现的,也就是说主线程调用了子线程的join()方法后,相当于主线程调用了子线程的wait()方法,主线程调用了子线程的wait方法后就会进入阻塞状态,相当于放弃了cpu的使用权,join(0)相当于forever。
浙公网安备 33010602011771号