スレッドが交代でプリントするJavaの仕組み

synchronized キーワードと wait()、notify() メソッドを用いて、2 つのスレッドによる交互の出力を行う

以下は簡単な例です。Aスレッドは奇数を、Bスレッドは偶数をプリントします。

public class AlternatePrint {
    private int count = 1;
    private final Object lock = new Object();

    public static void main(String[] args) {
        AlternatePrint alternatePrint = new AlternatePrint();
        Thread threadA = new Thread(() -> alternatePrint.printOdd());
        Thread threadB = new Thread(() -> alternatePrint.printEven());
        threadA.start();
        threadB.start();
    }

    public void printOdd() {
        while (count <= 100) {
            synchronized (lock) {
                if (count % 2 != 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + count);
                    count++;
                    lock.notify(); // 唤醒等待的线程
                } else {
                    try {
                        lock.wait(); // 当前线程等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void printEven() {
        while (count <= 100) {
            synchronized (lock) {
                if (count % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + count);
                    count++;
                    lock.notify(); // 唤醒等待的线程
                } else {
                    try {
                        lock.wait(); // 当前线程等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

上記例では、共有ロックオブジェクトlockをロックとして用い、各スレッドはsynchronized(lock)でロックオブジェクトを取得します。countが奇数のときはAスレッドがcountの表示と加算を行い、その後lock.notify()メソッドを呼び出して待機状態にあるBスレッドを待ち起こします。countが偶数のときはBスレッドがcountの表示と加算を行い、その後lock.notify()メソッドを呼び出して待機状態にあるAスレッドを待ち起こします。countの値が現在スレッドの表示条件に合致しない場合、現在スレッドはlock.wait()メソッドを呼び出すことで待機状態に移り、呼び起こされるまで待ちます。

ロック.wait() とロック.notify() メソッドは synchronized ブロック内でしか呼べません。呼び出さないと IllegalMonitorStateException 例外が発生する点に注意してください。また、スレッドの開始順序は確定していないので、A と B スレッドの印字順序が異なる可能性があります。

bannerAds