首頁  >  文章  >  Java  >  Java常用的四個執行緒函數有哪些?

Java常用的四個執行緒函數有哪些?

WBOY
WBOY轉載
2023-04-26 14:01:071350瀏覽

1. wait()

使當前執行緒等待,直到它被喚醒,通常是透過被通知或中斷,或直到經過一定的即時時間。

本身屬於一個Object 類,查看原始碼也可知:public class Object {

#查看其原始碼可知,一共有三個重載的方法,詳情原始碼如下:

//第一个重载函数
public final void wait() throws InterruptedException {
        wait(0L);
    }
    
//第二个重载函数
public final native void wait(long timeoutMillis) throws InterruptedException;


//第三个重载函数
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
        if (timeoutMillis < 0) {
            throw new IllegalArgumentException("timeoutMillis value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
            timeoutMillis++;
        }

        wait(timeoutMillis);
    }

具體實戰呼叫程式碼如下:

如果執行到了wait函數,在這4秒內,會釋放鎖定,並且暫停執行緒。如果這四秒內配合notify()可以喚醒並且得到鎖,如果沒有喚醒,等待其他來競爭。 4秒結束後,會預設自動釋放鎖定

目前執行緒在Thread.wait()等待過程中,如果Thread結束了,是可以自動喚醒的而且自動釋放鎖定

@Override
public void run() {
       synchronized (a) {
           a.wait(4000);      
       }
}

2 . join()

join是Thread類別的方法

查看其原始碼,具體源碼如下,三個重載的方法

//第一个重载函数
public final synchronized void join(final long millis)
    throws InterruptedException {
        if (millis > 0) {
            if (isAlive()) {
                final long startTime = System.nanoTime();
                long delay = millis;
                do {
                    wait(delay);
                } while (isAlive() && (delay = millis -
                        TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0);
            }
        } else if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            throw new IllegalArgumentException("timeout value is negative");
        }
    }


//第二个重载函数
/*等待该线程死亡的时间最多为毫秒加纳秒。 如果两个参数都为0,则意味着永远等待。  
这个实现使用了This的循环。 等待电话以this.isAlive为条件。 当一个线程终止this。 
调用notifyAll方法。 建议应用程序不要使用wait、notify或notifyAll on Thread实例。  */
public final synchronized void join(long millis, int nanos)
throws InterruptedException {

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos > 0 && millis < Long.MAX_VALUE) {
        millis++;
    }

    join(millis);
}


//第三个重载函数
/*等待线程死亡。  
此方法的调用与调用的行为完全相同  

InterruptedException—如果任何线程中断了当前线程。 当抛出此异常时,当前线程的中断状态将被清除。  */
public final void join() throws InterruptedException {
     join(0);
 }

主要的時間參數邏輯如下:

  • 小於0,拋出例外

  • 等於0,join(A),判斷A是否存在,存在才執行運算。該執行緒執行wait(0)等待,等待A執行緒執行完後才可結束

  • #大於0,同上,只不過執行的是wait(long millis),等待時間結束後才可繼續執行操作

3. sleep()

比較上一個wait函數

  • ##sleep(long mills) :讓出CPU資源,但不會釋放鎖定資源。

  • wait():讓出CPU資源與鎖定資源。

查看sleep函數的原始碼,一共有兩個重載函數

#都是Thread類別的函數

/*根据系统计时器和调度器的精度和准确性,
使当前执行的线程在指定的毫秒数内处于睡眠状态(暂时停止执行)。 
线程不会失去任何监视器的所有权。*/
public static native void sleep(long millis) throws InterruptedException;



/*导致当前执行的线程在指定的毫秒数加上指定的纳秒数
(取决于系统计时器和调度器的精度和准确性)内休眠(暂时停止执行)。 
线程不会失去任何监视器的所有权。  */
public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0 && millis < Long.MAX_VALUE) {
            millis++;
        }

        sleep(millis);
    }

4. yield()

查看yield()函數的原始碼,一個重載函數

都是Thread類別的函數

向調度器暗示當前執行緒願意放棄目前對處理器的使用。調度器可以忽略這個提示。

Yield是一種啟發式嘗試,旨在改善執行緒之間的相對進程,否則會過度使用CPU。它的使用應該與詳細的分析和基準測試相結合,以確保它實際上具有預期的效果。

使用這種方法很少是合適的。它可能用於調試或測試目的,在這些目的中,它可能有助於由於競爭條件而重新生成錯誤。在設計並發控制構造(如java.util.concurrent.locks套件中的構造)時,它可能也很有用。

public static native void yield();

總的來說,yield函數的功能主要是:

讓出CPU調度,暫停線程,但不能由使用者指定時間

只能讓同優先級有執行機會

5. 總結

wait 暫停該線程,讓出cpu,釋放鎖定。 (Object類別)

join暫停該線程,執行該線程之後才能回到自身的線程運行。 (Thread類別)

sleep 暫停該線程,讓出cpu,不釋放鎖定。 (Thread類別)

yield 暫停該線程,但是不能由使用者制定,只能讓同優先順序有執行機會。 (Thread類別)

5.1 wait與join的區別

看完以上的原始碼以及邏輯程式碼,再講講兩者的異同

總的來說

  • wait函數:讓目前執行緒進入等待狀態,wait()會與notify()和notifyAll()方法一起使用。 notify為喚醒函數

  • join函數:等待這個執行緒結束才能執行自已的執行緒。它的主要起同步作用,使執行緒之間的執行從「並行」變成「串列」。線程A中呼叫了線程B的join()方法時,線程

執行過程改變:線程A,必須等待線程B執行完畢後,才可以繼續執行下去

共同點:

  • 暫停目前的執行緒

  • 都可以透過中斷來喚醒

不同點在於:

區別waitjoin##類別目的同步5.2 wait和sleep的區別
Object類別 Thread類別
執行緒間通訊 排序,讓其串列通過
必須要synchronized #可以不用synchronized

wait():讓出CPU資源和鎖定資源。

sleep(long mills):讓出CPU資源,但不會釋放鎖定資源。

看區別,主要是看CPU的運作機制:

它們的差異主要考慮兩點:1.cpu是否繼續執行、2.鎖是否釋放掉。

歸根到底:

wait,notify,notifyall 都是Object物件的方法,是一起使用的,用於鎖定機制,所以會釋放鎖定

而sleep是Thread類,跟鎖沒關係,不會釋放鎖定

但兩者都會讓出cpu資源

以上是Java常用的四個執行緒函數有哪些?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除