在读到《java多线程编程核心技术》的3.2节“jion方法的使用”的时候,看到如下代码,便有了这篇总结的文章。
TheadA.java:
public class ThreadA extends Thread {
private ThreadB b;
public ThreadA(ThreadB b) {
super();
this.b = b;
}
@Override
public void run() {
try {
synchronized (b) {
System.out.println("begin A ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" end A ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ThreadB.java:
public class ThreadB extends Thread {
@Override
synchronized public void run() {
try {
System.out.println("begin B ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" end B ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main.java
public class Main{
public static void main(String[] args) {
try {
ThreadB b = new ThreadB();
ThreadA a = new ThreadA(b);
a.start();
b.start();
b.join(2000);
System.out.println(" main end "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
jion方法的源代码:
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;
}
}
}
如上的3个类,组成的这篇博文的主角。当我们执行main方法后,有几率会出现如下顺序的日志:
- 日志1:
begin A ThreadName=Thread-1 1545465206016
end A ThreadName=Thread-1 1545465211018
main end 1545465211019
begin B ThreadName=Thread-0 1545465211020
end B ThreadName=Thread-0 1545465216028
根据该日志的打印顺序和结果来看:
- b.join(2000)处,jion方法拿到锁,然后在jion方法里执行到wait()时释放锁。
- 线程a获得锁,TheadA类的run()中的sleep(5000)处阻塞,直到run()方法执行完毕,线程a释放锁。在进入run方法2s后,b.jion()方法在wait()处被唤醒,进入激活队列等待执行。
- b.jion(2000)和线程b竞争锁,结果b.jion(2000)得到锁,然后执行wait()方法和面的代码,jion()方法执行完,然后释放锁。
4.现在main线程和b线程异步执行,但是main线程的system.out.print()先于线程b的输出执行。
- 日志2:
begin A ThreadName=Thread-1 1545467317710
end A ThreadName=Thread-1 1545467322712
begin B ThreadName=Thread-0 1545467322714
main end 1545467322714
end B ThreadName=Thread-0 1545467327715
根据该日志的打印顺序和结果来看:
- b.join(2000)处,jion方法拿到锁,然后在jion方法里执行到wait()时释放锁。
- 线程a获得锁,TheadA类的run()中的sleep(5000)处阻塞,直到run()方法执行完毕,线程a释放锁。在进入run方法2s后,b.jion()方法在wait()处被唤醒,进入激活队列等待执行。
- b.jion(2000)和线程b竞争锁,结果b.jion(2000)得到锁,然后执行wait()方法和面的代码,jion()方法执行完,然后释放锁。
- 现在main线程和b线程异步执行,但是main线程的system.out.print()后于线程b的输出执行。