Java - 執行緒 交互輸出1-50的數字

By sunwc 2023-03-24 Java

執行緒通訊

Multi-threading 中 如何讓執行緒可以交互執行 會涉及到三個方法:

  • java.lang.Object.wait():一但執行此方法,當前執行緒就會進入阻塞狀態,並釋放同步鎖
  • java.lang.Object.notify():一但執行此方法,就會喚醒正在wait()中的執行緒。如果有多個執行緒wait()中,就先喚醒優先級較高的
  • java.lang.Object.notifyAll():一但執行此方法,就會喚醒所有wait()中的執行緒

wait(),notify(),notifyAll()使用前提

  • 這三個方法只能使用在synchronized修飾的區塊 或 同步方法中
  • 這三個方法的調用者必須是同步鎖this;若調用此三個方法的物件與同步鎖不一致,會出現IllegalMonitorStateException

例子

/**
 * @author sunwc
 * @create 2023-03-24 下午 03:02
 */
public class PrintNumberInteraction {

    public static void main(String[] args) {

        Number number = new Number();

        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);

        t1.setName("thread 1");
        t2.setName("thread 2");

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

    }

}

class Number implements Runnable {

    private int number = 1;

    @Override
    public void run() {

        while (number <= 50) {

            synchronized (this) {
                // 喚醒阻塞中的執行緒
                this.notify();

                if (number <= 50) {
                    System.out.println(Thread.currentThread().getName() + ": number - " + number);
                    number++;
                }

                try {
                    // 當前執行緒阻塞並釋放同步鎖,讓其它執行緒進入
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

輸出結果:

thread 2: number - 1
thread 1: number - 2
thread 2: number - 3
thread 1: number - 4
thread 2: number - 5
thread 1: number - 6
thread 2: number - 7
thread 1: number - 8
thread 2: number - 9
thread 1: number - 10
thread 2: number - 11
thread 1: number - 12
thread 2: number - 13
thread 1: number - 14
thread 2: number - 15
thread 1: number - 16
thread 2: number - 17
thread 1: number - 18
thread 2: number - 19
thread 1: number - 20
thread 2: number - 21
thread 1: number - 22
thread 2: number - 23
thread 1: number - 24
thread 2: number - 25
thread 1: number - 26
thread 2: number - 27
thread 1: number - 28
thread 2: number - 29
thread 1: number - 30
thread 2: number - 31
thread 1: number - 32
thread 2: number - 33
thread 1: number - 34
thread 2: number - 35
thread 1: number - 36
thread 2: number - 37
thread 1: number - 38
thread 2: number - 39
thread 1: number - 40
thread 2: number - 41
thread 1: number - 42
thread 2: number - 43
thread 1: number - 44
thread 2: number - 45
thread 1: number - 46
thread 2: number - 47
thread 1: number - 48
thread 2: number - 49
thread 1: number - 50

總結

java.lang.Thread.sleep() vs. java.lang.Object.wait()

  • 相同點:一但執行方法,都可以使得當前執行緒進入阻塞狀態
  • 不同點:

1.調用的要求不同:sleep()可以在任何需要的場景下使用;wait()必須使用在 synchronized修飾的區塊 或 同步方法中

2.關於是否釋放同步鎖:若兩的方法都使用在 synchronized 結構中,sleep不會釋放鎖;而wait()會釋放鎖