文章目录
sleep(long)源码join(long)源码小结join()后面代码提前运行的原因
sleep(long)源码
public static native void sleep(long millis
) throws InterruptedException
;
join(long)源码
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(long)的功能在内部是使用wait(long)方法来实现的,所以join(long)方法具有释放锁的特点。从源代码中可以了解到,当执行wait(long)方法后,当前线程的锁被释放,那么其他线程就可以调用此线程中的同步方法了。而Thread.sleep(long)方法却不释放锁。
join()后面代码提前运行的原因
代码演示
public class ThreadA extends Thread {
private final Thread b
;
public ThreadA(Thread b
, String name
) {
this.b
= b
;
this.setName(name
);
}
@Override
public void run() {
synchronized (b
) {
System
.out
.println(this.getName() + " 开始: " + System
.currentTimeMillis());
try {
Thread
.sleep(5000);
} catch (InterruptedException e
) {
e
.printStackTrace();
}
System
.out
.println(this.getName() + " 结束: " + System
.currentTimeMillis());
}
}
}
public class ThreadB extends Thread {
public ThreadB(String name
) {
this.setName(name
);
}
@Override
synchronized public void run() {
System
.out
.println(this.getName() + " 开始: " + System
.currentTimeMillis());
try {
Thread
.sleep(5000);
} catch (InterruptedException e
) {
e
.printStackTrace();
}
System
.out
.println(this.getName() + " 结束: " + System
.currentTimeMillis());
}
}
public class Run {
public static void main(String
[] args
) throws InterruptedException
{
ThreadB threadB
= new ThreadB("B");
ThreadA threadA
= new ThreadA(threadB
, "A");
threadA
.start();
threadB
.start();
threadB
.join(2000);
System
.out
.println(Thread
.currentThread().getName() + " 结束" +
System
.currentTimeMillis());
}
}
运行结果 所以可以完全确定地得出一个结论:方法join(2000)大部分是先运行的,也就是先抢到ThreadB的锁,然后快速进行释放。看一下运行结果的解释: 1 ) b.join(2000)方法先抢到B锁,然后将B锁进行释放; 2 )ThreadA抢到锁,打印ThreadA 开始并且sleep(5000); 3 ) ThreadA打印ThreadA 结束,并释放锁; 4)这时join(2000)和ThreadB争抢锁,而join(2000)再次抢到锁,发现时间已过,释放锁后打印main end; 5 )ThreadB抢到锁打印ThreadB 开始; 6)5秒之后再打印ThreadB 结束。