1. 程式人生 > >Java執行緒休眠方法sleep、執行緒讓步yield和join方法

Java執行緒休眠方法sleep、執行緒讓步yield和join方法

執行緒休眠(sleep方法)

執行緒休眠:讓執行緒暫緩執行,等到預計時間之後再恢復執行。

執行緒休眠會交出cpu,讓cpu去執行其他任務,但是不會釋放鎖。
比如:當前執行緒sleep休眠了,但是如果此執行緒在休眠前持有某個物件的鎖,那就算它休眠了其他執行緒也不能獲取到這個物件的鎖。

注意:呼叫sleep結束後執行緒會重新回到就緒狀態,只需要等待獲取cpu執行就可以。

方法:

public static native void sleep(long millis) throws InterruptedException

休眠的時間是以毫秒為單位
使用:

class MyThread implements Runnable{ @Override public void run() { for(int i = 0; i < 5; i++){ try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" i=" + i); } } } public class Test{ public static void main(String[] args){ MyThread myThread = new MyThread(); new Thread(myThread).start(); new Thread(myThread).start(); new Thread(myThread).start(); } }

執行緒讓步(yield()方法)

yield():暫停當前正在執行的執行緒物件,並執行其他執行緒。

執行緒讓步會交出cpu許可權,讓cpu去執行其他的執行緒。和sleep方法類似,同樣不會釋放鎖,但是yield不能控制具體交出cpu的時間,並且,yield方法只能讓擁有相同優先順序的執行緒有獲取cpu執行的機會。

注意:呼叫yield結束後執行緒會重新回到就緒狀態,只需要等待獲取cpu執行就可以。

使用:

class MyThread implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            Thread.yield();
            System.out.println(Thread.currentThread().getName()+" i=" + i);
        }
    }
}

public class Test{
    public static void main(String[] args){
        MyThread myThread = new MyThread();
        new Thread(myThread).start();
        new Thread(myThread).start();
        new Thread(myThread).start();
    }
}

等待其他執行緒終止-join()方法

意思就是說如果在主執行緒中呼叫這個方法時會讓主執行緒休眠,讓呼叫該方法的執行緒run方法先執行完畢後再開始執行主執行緒。
在這裡插入圖片描述
join放發實際上是對wait方法的封裝。

我們來看join的原始碼

public final void join() throws InterruptedException {
        join(0);
    }

我們可以看到join方法實際上是呼叫了join(0);

join(long millis)方法如下:


    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(0)呼叫的部分程式碼;如下:

if (millis == 0) {
            while (isAlive()) {//判斷當前執行緒是否為Running狀態
                wait(0);
            }

從上面可以看出如果呼叫此方法的執行緒是正在執行的執行緒,那麼就會呼叫wait(0)方法,

關於wait()的原始碼:

    public final native void wait(long timeout) throws InterruptedException;

wait(long timeout)是一個本地方法,呼叫本機的原生系統函式,當Thread類被載入到JVM中的時候,它就會呼叫註冊相應的本地方法。
wait(0)就是讓其他執行緒一直在等待,當此執行緒終止時,會呼叫執行緒自身的notifyAll()方法,喚醒所有等待在該執行緒物件上的執行緒。

使用:

public class Test{
    public static void main(String[] args) throws InterruptedException {

        final Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t1");
            }
        });
        final Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2");
            }
        });
        final Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t3");
            }
        });

        t1.start();
        t3.start();
        
        t2.start();


    }
}

執行結果:

t1
t2
t3

當t2比t3start時間遲的時候,出現下面結果

public class Test{
    public static void main(String[] args) throws InterruptedException {

        final Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t1");
            }
        });
        final Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2");
            }
        });
        final Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t3");
            }
        });

        t1.start();
        t3.start();
        Thread.sleep(2000);//讓主執行緒休眠2秒,那麼在t3呼叫join時t2還不是執行狀態
        t2.start();


    }
}

執行結果如下:

t1
t3
t2

這就是因為join(0)中呼叫了

if (millis == 0) {
            while (isAlive()) {//判斷當前執行緒是否為Running狀態
                wait(0);
            }

因為t2不處於執行狀態所以不會執行wait(0),所以t3就不會等待,直接執行下一條語句。