1. ホーム
  2. java

[解決済み] 他のスレッドが終了したかどうかを知るには?

2022-06-14 15:26:55

質問

という名前のメソッドを持つオブジェクトがあります。 StartDownload() というメソッドを持つオブジェクトがあり、3つのスレッドを起動します。

各スレッドの実行が終了したときに通知を受けるにはどうしたらよいでしょうか。

スレッドの1つ(またはすべて)が終了したのか、まだ実行中なのかを知る方法はありますか?

どのように解決するのですか?

いくつかの方法があります。

  1. 使用する Thread.join() を使用して、各スレッドの完了をブロッキング方式で待ちます。
  2. チェック Thread.isAlive() を、ポーリング方式で -- 一般的には推奨されません -- 各スレッドが完了するまで待つ、あるいは
  3. 非正統的な方法で、問題の各スレッドについて、以下のように呼び出します。 setUncaughtExceptionHandler を呼び出す。 を呼び出してオブジェクトのメソッドを呼び、各スレッドが完了したときに捕捉されない例外を投げるようにプログラムするか、あるいは
  4. のロックやシンクロナイザー、メカニズムを使用する。 java.util.concurrent または
  5. よりオーソドックスに、メインスレッドにリスナーを作成し、各スレッドが完了したことをリスナーに伝えるようにプログラムします。

アイデア⑤を実装するには? まず、インターフェイスを作成するのが一つの方法です。

public interface ThreadCompleteListener {
    void notifyOfThreadComplete(final Thread thread);
}

で、以下のようなクラスを作成します。

public abstract class NotifyingThread extends Thread {
  private final Set<ThreadCompleteListener> listeners
                   = new CopyOnWriteArraySet<ThreadCompleteListener>();
  public final void addListener(final ThreadCompleteListener listener) {
    listeners.add(listener);
  }
  public final void removeListener(final ThreadCompleteListener listener) {
    listeners.remove(listener);
  }
  private final void notifyListeners() {
    for (ThreadCompleteListener listener : listeners) {
      listener.notifyOfThreadComplete(this);
    }
  }
  @Override
  public final void run() {
    try {
      doRun();
    } finally {
      notifyListeners();
    }
  }
  public abstract void doRun();
}

を拡張し、各スレッドは NotifyingThread を実装する代わりに run() を実装する代わりに doRun() . したがって、それらが完了すると、通知を待っている人に自動的に通知されます。

最後に、メインクラス(すべてのスレッド(または少なくとも通知を待っているオブジェクト)を開始するもの)で、そのクラスを次のように修正します。 implement ThreadCompleteListener に変更し、各スレッドを作成した直後にリスナーのリストに自分自身を追加します。

NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start();           // Start the Thread

とすると、各スレッドが終了するときに、あなたの notifyOfThreadComplete メソッドは、ちょうど終了した(またはクラッシュした)スレッドのインスタンスで呼び出されます。

なお、より良い方法は implements Runnable よりも extends Thread に対して NotifyingThread のように、Threadを拡張することは通常新しいコードでは推奨されません。 しかし、私はあなたの質問に対してコーディングしています。 を変更すると NotifyingThread クラスを実装するために Runnable を実装する場合、Threads を管理するコードの一部を変更する必要がありますが、これは非常に簡単なことです。