- 首先看一下方法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)方法,
就會立即(幾乎是立即)交出鎖,
*/
運行結果: