Java線程部分join(long)跟sleep(long)的區別

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

運行結果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章