Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaにおけるスレッド間通信の方法とは?wait()・notify()・notifyAll()の使い方

スレッド間通信とは、複数のスレッドが互いに状態を通知し合いながら協調して動作する仕組みのことです。Javaでは、このスレッド間通信を実現するために、Objectクラスに定義された3つのメソッドが主に使用されます。

wait()

wait()メソッドを呼び出すと、現在実行中のスレッドは保持しているロック(モニターロック)を解放し、待機状態へ移行します。その後、指定された時間が経過するか、別のスレッドが同じオブジェクトに対してnotify()またはnotifyAll()メソッドを呼び出すまで、スレッドは待ち続けます。

なお、wait()は必ずsynchronizedブロックやsynchronizedメソッド内で呼び出す必要があります。そうしないとIllegalMonitorStateExceptionが発生します。

notify()

notify()メソッドは、現在のオブジェクトのモニター上で待機している複数のスレッドの中から、1つのスレッドだけを再開(起床)させます。どのスレッドが選ばれるかはJVMが任意に決定するため、特定のスレッドを指定することはできません。

notifyAll()

notifyAll()メソッドは、現在のオブジェクトのモニター上で待機しているすべてのスレッドを再開させます。ただし、再開された全スレッドが同時に処理を進められるわけではなく、ロックを獲得できたスレッドから順番に実行されます。

サンプルコード

以下は、銀行口座を模したクラスを使って、預け入れ処理が完了した際に他のスレッドへ通知を行う例です。

class BankClient {
    int balAmount = 5000;
    synchronized void withdrawMoney(int amount) {
        System.out.println("Withdrawing money");
        balAmount -= amount;
        System.out.println("The balance amount is: " + balAmount);
    }
    synchronized void depositMoney(int amount) {
        System.out.println("Depositing money");
        balAmount += amount;
        System.out.println("The balance amount is: " + balAmount);
        notify();
    }
}
public class ThreadCommunicationTest {
    public static void main(String args[]) {
        final BankClient client = new BankClient();
        new Thread() {
            public void run() {
                client.withdrawMoney(3000);
            }
        }.start();
        new Thread() {
            public void run() {
                client.depositMoney(2000);
            }
        }.start();
    }
}

この例では、出金と入金を行う2つのスレッドが同じBankClientオブジェクトを共有しています。両方のメソッドがsynchronizedで修飾されているため、同時に実行されることはありません。また、入金処理の最後にnotify()を呼び出すことで、待機中のスレッドが存在する場合に通知を送る構造になっています。

実行結果

Withdrawing money
The balance amount is: 2000
Depositing money
The balance amount is: 4000

このように、wait()notify()notifyAll()を組み合わせることで、複数のスレッドがロックを競合することなく、互いの状態を把握しながら安全にデータを共有できるようになります。生産者・消費者問題など、マルチスレッドプログラミングにおける典型的な同期処理の基礎となる重要な概念です。

  1. JavaでJTableHeaderの各列にツールチップを設定する方法

    JTableHeaderはJComponentクラスのサブクラスであり、テーブルのヘッダー部分を管理するためのコンポーネントです。JTableオブジェクトを生成すると、そのコンストラクタが自動的に新しいJTableHeaderオブジェクトを作成し、テーブルのヘッダーを管理します。JTableには、テーブルヘッダーコンポーネントとしてJTableHeaderオブジェクトを設定するためのsetTableHeader()メソッドと、設定済みのJTableHeaderオブジェクトへの参照を取得するgetTableHeader()メソッドが用意されています。各列にツールチップを設定する仕組みJTable

  2. JavaのJTableで各列の幅を変更する方法をわかりやすく解説

    Java Swingで表形式のデータを扱う際、デフォルトの列幅では文字が切れてしまったり、レイアウトが崩れたりすることがあります。本記事では、JTableの各列の幅を自由に変更する方法を、基本の特徴からサンプルコードまで詳しく解説します。 JTableとは JTableは、複雑なデータ構造を表示するためのJComponentのサブクラスです。 MVC(Model View Controller)デザインパターンに基づいて設計されており、データを行と列の形式で表示できます。 DefaultTableModelクラスはAbstractTableModelを拡張したクラスで、JTableに対して行