代码实现
/**
* Created by Administrator on 2018/2/3.
*/
public class JoinTest {
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 2 seconds or if it's finished
*/
try {
/**
* main thread wait 2000ms for wait t1 execute finished
*/
t1.join(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
/**
* start third thread only when first thread is finished
* t.join() = t.join(0) JDK: A timeout of 0 means to wait forever 意思是永远等待,其实是等到t结束后
*/
try {
/**
* main thread wait t1 execute finished forever
*/
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t3.start();
/**
* let all threads finish execution before finishing main thread
*/
try {
/**
* main thread wait t2 execute finished forever
*/
t2.join();
/**
* main thread wait t3 execute finished forever
*/
t3.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("All threads are dead, exiting main thread");
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread started:::" + Thread.currentThread().getName());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread ended:::" + Thread.currentThread().getName());
}
}
关键剖析
Join可以实现线程的执行顺序,内部具体实现流程分析
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
public final void join() throws InterruptedException {
join(0);
}
/**
* synchronized修饰,获得锁
*/
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;
}
/**
* 调用Object的wait()方法会释放锁
*/
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
通过不断轮询的方式去观察线程是否还是活动线程
join(0)是不断的询问线程的状态,直到线程销毁join()方法才会结束。
当millis>0时,不在是wait(0),而是wait(delay),delay是还剩余的millis时间。有人会问第一次wait(delay)后不就已经经过这millis的时间,
为什么还会有while执行多次wait(delay)呢?因为这里不仅要考虑wait在delay时间后被唤醒,还要考虑到在delay时间内,被notify唤醒,唤醒后还没有执行到millis的时间,因此要多次调用wait(delay)方法。
join方法底层调用的是wait方法,但要实现wait的提前是要获得锁,执行到wait方法才可以释放锁,而sleep方法不释放锁。