[Java併發]

Duancf發表於2024-07-14

sleep()、wait()、join()、yield()

yield

在Java中,yield() 是一個Thread類的方法,它用於暫停當前執行緒並允許其他執行緒執行。它是一種執行緒排程的建議,告訴排程器可以切換到其他就緒狀態的執行緒。呼叫yield()方法後,執行緒會從執行狀態轉換為就緒狀態,讓其他執行緒有機會執行。

下面是一個簡單的Java程式碼示例,展示了yield()方法的用法:

public class YieldExample implements Runnable {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            // 呼叫 yield() 方法
            Thread.yield();
        }
    }

    public static void main(String[] args) {
        // 建立兩個執行緒
        Thread thread1 = new Thread(new YieldExample(), "Thread 1");
        Thread thread2 = new Thread(new YieldExample(), "Thread 2");

        // 啟動執行緒
        thread1.start();
        thread2.start();
    }
}

在上面的示例中,我們建立了兩個執行緒並啟動它們。每個執行緒都會列印從0到4的數字。在每次迴圈中,我們呼叫了yield()方法,這樣兩個執行緒就可以交替執行,讓出CPU時間給其他執行緒。

請注意,yield()方法的呼叫並不能保證當前執行緒一定會讓出CPU時間,它只是一個建議。實際執行結果取決於作業系統和執行緒排程器的具體實現。

join

在Java中,join() 是Thread類的一個方法,用於等待呼叫該方法的執行緒執行完畢。當一個執行緒呼叫另一個執行緒的 join() 方法時,呼叫執行緒將被阻塞,直到被呼叫的執行緒執行完畢。

join() 方法有以下兩種常見的用法:

  1. 使用 join() 方法等待單個執行緒完成:
Thread thread = new Thread(new MyRunnable());
thread.start();

// 在主執行緒中呼叫 join() 方法等待 thread 執行緒執行完畢
try {
    thread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

System.out.println("thread 執行完畢");

在上面的示例中,我們建立了一個新執行緒並啟動它。在主執行緒中,我們呼叫了join()方法等待新執行緒執行完畢。主執行緒會被阻塞,直到新執行緒執行完畢後才會繼續執行。

  1. 使用 join() 方法等待多個執行緒完成:
Thread thread1 = new Thread(new MyRunnable());
Thread thread2 = new Thread(new MyRunnable());

thread1.start();
thread2.start();

// 在主執行緒中分別呼叫 join() 方法等待 thread1 和 thread2 執行緒執行完畢
try {
    thread1.join();
    thread2.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

System.out.println("thread1 和 thread2 執行完畢");

在上面的示例中,我們建立了兩個新執行緒,並啟動它們。然後在主執行緒中分別呼叫兩個執行緒的 join() 方法,以等待它們執行完畢。主執行緒會被阻塞,直到兩個執行緒都執行完畢後才會繼續執行。

需要注意的是,join() 方法可能會丟擲 InterruptedException,因此在使用時需要處理異常。這是由於執行緒在等待期間可能被中斷,導致 join() 方法提前返回。

使用 join() 方法可以實現執行緒之間的協作和同步,確保某個執行緒在其他執行緒執行完畢後再繼續執行。

sleep

在Java中,sleep() 是Thread類的一個靜態方法,用於暫停當前執行緒的執行一段指定的時間。它是一種執行緒睡眠的機制。

sleep() 方法有以下兩種常見的用法:

  1. 使用 sleep() 方法暫停當前執行緒的執行:
try {
    // 暫停當前執行緒執行 500 毫秒(0.5 秒)
    Thread.sleep(500);
} catch (InterruptedException e) {
    e.printStackTrace();
}

System.out.println("執行緒睡眠後繼續執行");

在上面的示例中,我們使用 sleep() 方法暫停當前執行緒的執行。在這個例子中,當前執行緒將會睡眠500毫秒(0.5秒),然後繼續執行後續的程式碼。

需要注意的是,sleep() 方法可能會丟擲 InterruptedException,因此在使用時需要處理異常。這是由於執行緒在睡眠期間可能被中斷,導致 sleep() 方法提前返回。

  1. 使用 sleep() 方法實現定時任務:
class MyTask implements Runnable {
    public void run() {
        try {
            // 定時任務,每隔 1 秒執行一次
            while (true) {
                System.out.println("執行定時任務");
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// 建立一個新執行緒執行定時任務
Thread thread = new Thread(new MyTask());
thread.start();

在上面的示例中,我們建立了一個新執行緒來執行定時任務。在定時任務的迴圈中,我們使用 sleep() 方法使執行緒睡眠1秒,然後再執行下一次迴圈。這樣就可以實現定時任務的效果。

需要注意的是,sleep() 方法會暫停當前執行緒的執行,但不會釋放鎖。如果在同步程式碼塊或同步方法中呼叫 sleep() 方法,其他執行緒仍然無法獲取到該鎖。因此,在使用 sleep() 方法時要注意對鎖的使用,避免可能的執行緒競爭和死鎖問題。

總結:
sleep() 方法用於暫停當前執行緒的執行一段指定的時間。它可以用於實現執行緒的延時執行、定時任務等場景。然而,需要注意處理可能丟擲的 InterruptedException 異常,並避免在同步程式碼塊或同步方法中使用 sleep() 方法導致的執行緒競爭和死鎖問題。

wait

在Java中,wait() 是Object類的一個方法,用於使當前執行緒進入等待狀態,直到其他執行緒呼叫相同物件上的 notify()notifyAll() 方法來喚醒等待執行緒。

wait() 方法有以下常見的用法:

  1. 在同步程式碼塊中使用 wait() 方法:
synchronized (sharedObject) {
    try {
        // 當前執行緒進入等待狀態,釋放物件的鎖
        sharedObject.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    // 當執行緒被喚醒後,繼續執行
    System.out.println("執行緒被喚醒");
}

在上面的示例中,我們在一個同步程式碼塊中呼叫了 wait() 方法。當執行緒執行到 wait() 方法時,它會釋放物件的鎖並進入等待狀態,直到其他執行緒呼叫相同物件上的 notify()notifyAll() 方法來喚醒等待執行緒。

需要注意的是,在呼叫 wait() 方法前必須獲得物件的鎖,因此通常在同步程式碼塊或同步方法中使用 wait() 方法。

  1. 使用 wait() 方法實現執行緒間的協作:
class MyTask implements Runnable {
    private final Object lock;

    public MyTask(Object lock) {
        this.lock = lock;
    }

    public void run() {
        synchronized (lock) {
            try {
                System.out.println("執行緒開始執行任務");

                // 執行任務的一部分

                // 等待其他執行緒完成特定條件
                lock.wait();

                // 執行緒被喚醒後繼續執行任務的剩餘部分
                System.out.println("執行緒繼續執行任務");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

// 建立一個共享的鎖物件
Object lock = new Object();

// 建立一個新執行緒執行任務
Thread thread = new Thread(new MyTask(lock));
thread.start();

// 在適當的時機喚醒等待的執行緒
synchronized (lock) {
    lock.notify();
}

在上面的示例中,我們建立了一個共享的鎖物件,並在一個新執行緒的任務中使用 wait() 方法進行等待。主執行緒在適當的時機呼叫 notify() 方法來喚醒等待的執行緒。

需要注意的是,wait() 方法必須在同步塊中使用,並且在呼叫 wait() 方法前必須獲得物件的鎖,否則會丟擲 IllegalMonitorStateException 異常。

總結:
wait() 方法用於使當前執行緒進入等待狀態,直到其他執行緒呼叫相同物件上的 notify()notifyAll() 方法來喚醒等待執行緒。它常用於執行緒間的協作和同步。需要在同步塊中使用 wait() 方法,並在呼叫 wait() 方法前獲得物件的鎖。同時,需要注意處理可能丟擲的 InterruptedException 異常和使用適當的喚醒機制。

相關文章