7

私は自分自身に並行性を教えようとしてきましたが、問題が発生しました。wait()2つのJavaスレッドがとを介して相互に通信できることを理解していnotify()ます。ただし、これには、一方のスレッドが非アクティブであり、もう一方のスレッドがウェイクアップするまで本質的に「ただ座っている」必要があります。

両方のスレッドを同時に実行し、それでも他のスレッドからの通知をリッスンさせることは可能ですか?これは、並行性の手法を介して達成されるのでしょうか、それとも代わりにActionListener

たとえば、私がこれをテストしているプロジェクトは、基本的に、さまざまなエンティティがさまざまなセルをさまよっているグリッドです。2つのエンティティがたまたま同じセルに迷い込んだ場合、一方が他方に通知し、これに基づいて別のことが発生するようにします(たとえば、「こんにちは!」という挨拶)。しかし、現状では、待機/通知パラダイムでは、スレッド/エンティティの1つが1つのセルに座って、別のセルがさまよっているのを待つ必要があります。両方を動かすことはできません。

4

5 に答える 5

5

スレッド間で通信する方法はいくつかあります。最も一般的なアプローチを使用すると、インスタンス変数を使用してスレッド間で情報を共有できますが、1つのスレッドからのみ書き込むか、共有変数への更新を同期するように注意する必要があります。または、スレッド間通信用に設計されたパイプI / Oストリームを使用したり、スレッド間で生データを渡したりすることもできます。一方のスレッドはストリームに情報を書き込み、もう一方のスレッドはそれを読み取ります。

これは、低速のネットワーク接続からの出力を読み取り、スレッドを使用してSystem.outにダンプするメソッドの例です。

    public void threads() throws IOException {
    final PipedOutputStream outputForMainThread = new PipedOutputStream();
    new Thread(new Runnable() {
        @Override
        public void run() {
            while(moreDataOnNetwork()) {
                byte[] data = readDataFromNetwork();
                try {
                    outputForMainThread.write(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
    BufferedReader reader = new BufferedReader(new InputStreamReader(new PipedInputStream(outputForMainThread)));
    for(String eachLine = reader.readLine(); eachLine != null; eachLine = reader.readLine()) {
        System.out.println(eachLine);
    }
}

ただし、一方のスレッド(ユーザーインターフェイススレッド)が特定の条件を検出したときにもう一方のスレッドに通知されるイベントコールバックメカニズムが必要なようです。プラットフォームによっては、これの多くが組み込まれています。たとえば、Androidを使用すると、グリッドエンティティが移動したことを判断するスレッドを作成できます。画面を再描画するために、メインのユーザーインターフェイススレッドに更新を送信します。このような更新は次のようになります。

public void gridEntityDidUpdate(final Point fromLocation, final Point toLocation) {
    Activity activity = getMainActivity();
    activity.runOnUiThread(
            new Runnable() {
                @Override
                public void run() {
                    updateScreen(fromLocation, toLocation);
                    if(pointsAreCoincedent(fromLocation, toLocation)) {
                        System.out.println("Hello there!");
                    }
                }
            }
    );
}

private void updateScreen(Point fromLocation, Point toLocation) {
    //Update the main activity screen here
}

このシナリオでは、画面上のすべての要素の位置を計算し、要素の位置が変更されたときにメインスレッドに通知するバックグラウンドスレッドがあります。2つのポイントが一致するか同じであるかを判断する抽出されたメソッドがあります。

于 2012-10-01T16:30:06.443 に答える
1

Erlang 言語を使用して、スレッドのより優れた安全な代替手段として、独自のアドレス空間内で実行される言語間で安全に通信できます。ProcessesJava

于 2012-10-01T16:34:52.847 に答える
1

私は自分自身に並行性を教えようとしてきましたが、問題が発生しました。2つのJavaスレッドがwait()とnotify()を介して相互に通信できることを理解しています。

「古典的な」Javaスレッドチュートリアルは、早い段階で待機/通知を教えます。Java 1.1、1.2の時間枠に戻ると、これですべてです。

ただし、BrianGoetzによる優れた「JavaConcurrencyin Practice」のコピーを入手できる場合は、セクションIVの高度なトピックの第14章「カスタムシンクロナイザーの構築」まで待機/通知について説明しません。ここで言い換えると、「前の300ページを読んで、これまでに説明した構成要素がどれもニーズを満たしていない場合は、wait/notifyを使用して独自の構成を試してみてください」という印象を受けました。

私のポイントは、待機/通知は非常に重要ですが、並行性の学習を開始するのに最適な場所ではない可能性があるということです。この質問の回答/コメントの一部(プロデューサー/コンシューマー、ExecutorService)は、Java 5で追加された高レベルの並行性ビルディングブロックを参照しています。このようなものは後で追加されましたが、最初に学習する必要があります。

あなたの質問に戻ってください-ここにいくつかの考えがあります:

これがGUIアプリケーションであり、バックグラウンドスレッドに作業を行わせたい場合は、SwingWorkerを確認してください。私はSwingWorker(セクション9.3.3)を使用して成功しました。ここでは、バックグラウンドスレッドがブロッキングキューからメッセージを読み取り(セクション5.3)、いくつかの作業を行い、より高いレベルの「publish」メソッドを呼び出してGUIスレッドに通知します。「待機/通知」はありません-少なくとも私のコードにはありません。

アプリケーションがSwingベースではなく、異なるスレッドでタスクを並行して実行し、ときどき相互にメッセージを送信したい場合は、ZeroMQ「同時実行フレームワークとして機能するソケットライブラリ」を検討してください。ZeroMQを使用すると、各スレッドはメッセージを読み取って処理するイベントループを実行します。スレッドは、自身にメッセージを送信することにより、自身のスレッドで作業をスケジュールできます。そのスレッド(ソケット)にメッセージを送信することにより、作業をスケジュールしたり、別のスレッドに通知したりできます。

とにかく、頑張ってください。

于 2012-10-01T18:14:33.017 に答える
0

セマフォオブジェクトのようなThreadManagerクラスを使用してみてください。List<Thread>あなたのスレッドはそこから他のスレッドを見つけて参照できるはずです。

于 2012-10-01T16:37:04.173 に答える
0

両方のスレッドを同時に実行し、それでも他のスレッドからの通知をリッスンさせることは可能ですか?

彼らが待っていないときはいつでも、彼らは同時に何かをしている可能性があります。彼らがお互いを待っているように見える場合は、1つのスレッドを使用したほうがよい可能性があります。(複数のスレッドを使用することが常に良いとは限りません)

これは、同時実行技術または代わりにActionListenerのようなものを介して達成されますか?

問題をどのように分解したかに関する設計上の問題である可能性が高くなります。スレッド間の相互作用が最小限である場合に、スレッドが最適に機能します。それらが相互に大きく依存している場合は、使用するスレッドを少なくすることを検討する必要があります。

しかし、現状では、待機/通知パラダイムでは、スレッド/エンティティの1つが1つのセルに座って、別のセルがさまよっているのを待つ必要があります。

なぜここで待つ/通知する必要があるのか​​まったくわかりません。同じセルにいるときに、移動してメッセージを相互に送信するだけです。

于 2012-10-01T16:37:35.417 に答える