- 首先看一下方法join(long)的内部是怎么实现的:源码: 可以看出:内部是调用wait方法来实现的,而wait方法具有释放锁的特点,从源码可以看出执行wait方法之后,当前线程的锁被释放,那么其他线程就可以 调用此线程中的同步方法了
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);//注意此处,内部是调用wait方法来实现的;
now = System.currentTimeMillis() - base;
}
}
}
- 看一下sleep源码:是个本地的静态方法,由前面的学习我们知道sleep方法执行完是不能释放锁的,当sleep所在的方法内部的代码执行完了之后才会释放锁
public static native void sleep(long millis) throws InterruptedException;
- 实验验证sleep方法不释放锁:
/**
* 演示sleep方法具有不释放锁的特点;
*
*/
class Thread5A extends Thread{
private Thread5B thread5B;
public Thread5A(Thread5B thread5B) {
this.thread5B = thread5B;
}
@Override
public void run() {
try{
synchronized (thread5B){
thread5B.start();
Thread.sleep(6000);
System.out.println("sleep不释放锁------");
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
class Thread5B extends Thread{
@Override
public void run() {
try {
System.out.println("B线程的开始"+System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("B线程的结束"+System.currentTimeMillis());
}catch (InterruptedException e){
e.printStackTrace();
}
}
synchronized public void bService(){
System.out.println("调用一下B线程里的另外一个同步方法;"+System.currentTimeMillis());
}
}
class Thread5C extends Thread{
private Thread5B thread5B;
public Thread5C(Thread5B thread5B) {
this.thread5B = thread5B;
}
@Override
public void run() {
thread5B.bService();
}
}
public class Test5 {
public static void main(String[] args) throws InterruptedException {
Thread5B b = new Thread5B();
Thread5A a = new Thread5A(b);
a.start();
Thread.sleep(1000);
Thread5C c = new Thread5C(b);
c.start();
}
}
/*
运行结果:
B线程的开始1558623812333
B线程的结束1558623815333
sleep不释放锁------
调用一下B线程里的另外一个同步方法;1558623818324
注意最后C线程调用B线程另一个同步方法的时间,
一直从B线程开始执行等了6秒,
可是B线程3秒已经执行完了;
这是因为A线程持有B线程类对象的锁6秒
所以只有在A线程6秒结束释放B对象的锁的时候
才能调用ThreadB中的另外一个同步方法;
此实验证明sleep方法不释放锁;
*/
运行结果:
- 下面验证一下join()方法释放锁的特点
/**
* 验证join方法释放锁的特点
*/
class Thread6A extends Thread{
private Thread6B thread6B;
public Thread6A(Thread6B thread6B) {
this.thread6B = thread6B;
}
@Override
public void run() {
try{
synchronized (thread6B){
thread6B.start();
thread6B.join(4000);
System.out.println("sleep不释放锁------");
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
class Thread6B extends Thread{
@Override
public void run() {
try {
System.out.println("B线程的开始"+System.currentTimeMillis()+"----");
Thread.sleep(3000);
System.out.println("B线程的结束"+System.currentTimeMillis()+"----");
}catch (InterruptedException e){
e.printStackTrace();
}
}
synchronized public void bService(){
System.out.println("调用一下B线程里的另外一个同步方法;"+System.currentTimeMillis());
}
}
class Thread6C extends Thread{
private Thread6B thread6B;
public Thread6C(Thread6B thread6B) {
this.thread6B = thread6B;
}
@Override
public void run() {
thread6B.bService();
}
}
public class Test6{
public static void main(String[] args) throws InterruptedException {
Thread6B b = new Thread6B();
Thread6A a = new Thread6A(b);
a.start();
Thread.sleep(1000);
Thread6C c = new Thread6C(b);
c.start();
}
}
/*
运行结果:
B线程的开始1558787599534----
调用一下B线程里的另外一个同步方法;1558787600533
sleep不释放锁------
B线程的结束1558787602534----
实验多次证明,一旦在A线程里面B线程启动后调用了join(long)方法,
就会立即(几乎是立即)交出锁,
*/
运行结果: