Java join()方法、wait()方法和sleep()方法的理解

join()

join()方法來自於Thread,join()方法的作用是 阻塞 調用該方法的線程,使其進入 TIMED_WAITING 狀態,直到被調用的線程執行完畢,原方法繼續執行。

如以下代碼,在主線程中調用join()方法,會首先執行run()方法中的代碼。

當我們把join()方法給註釋掉,會發現,首先執行了主線程的代碼。

即 調用join()方法阻塞了主線程,當run()方法執行完畢,主線程方法繼續執行

    public static void main(String[] args) throws InterruptedException {
        WaitJoinAndSleep w = new WaitJoinAndSleep();

        Thread tOne = new Thread(w);
        tOne.setName("1號選手");
        tOne.start();
        tOne.join();
        System.out.println("main finished");

    }

    @Override
    public void run() {
        System.out.println("who first in:"+Thread.currentThread().getName());
            System.out.println("Thread Name:+"+Thread.currentThread().getName());
    }

//輸出
who first in:1號選手
Thread Name:+1號選手
main finished

//註釋掉tOne.join()後輸出
main finished
who first in:1號選手
Thread Name:+1號選手

join()方法源碼

通過join()方法源碼我們可以發現,join()方法最終是調用了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);
                now = System.currentTimeMillis() - base;
            }
        }
    }

wait()

wait()方法來自於Object。

wait()方法的作用是讓當前線程等待,即執行wait方法的線程等待,釋放鎖。等待其它線程調用notify()方法時再繼續運行。

如下代碼,當主線程調用start()方法。此時並不會運行run()方法。因爲此時鎖被主線程佔有。當主線程中代碼調用wait()方法,主線程釋放鎖,線程one獲得鎖。在run()方法中執行notify()方法後,主線程被喚醒,繼續執行。

總結:wait()方法是讓運行它自身的線程等待。需要注意的是wait(),notify()和notifyAll()方法需要在synchronized中調用

   public static void main(String[] args) throws InterruptedException {
        WaitDemo w = new WaitDemo();
        Thread one = new Thread(w);
        synchronized (WaitDemo.class) {
            // 開始啓動線程
            System.out.println("thread started:"+Thread.currentThread().getName());
            one.start();
            //  調用wait()方法
            System.out.println("begin start wait method");
            WaitDemo.class.wait();
            System.out.println("who started again");
        }
    }

    @Override
    public void run() {
        synchronized (WaitDemo.class) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("who come first:"+Thread.currentThread().getName());
            WaitDemo.class.notify();
        }
    }

// 輸出
thread started:main
begin start wait method
who come first:Thread-0
who started again

sleep()

sleep()方法屬於Thread

sleep()方法同樣可以造成線程阻塞,結合之前的代碼示例可以理解。調用sleep()方法並不會釋放鎖,而是讓當前線程“睡眠”,持有鎖的仍舊是當前線程,“睡眠時間”作爲參數,時間一到代碼繼續運行。

與wait()方法不同的是,sleep()方法可以在任意地方調用

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