proactor
システムデザインのスタイルに関連する問題が発生し始めています。この問題を解決するには、2つのスレッド間の通信が必要です。このコミュニケーションが何であるかを選ぶことは、それが乱雑になるところです。 thread1がソケットを読み込もうとするのを止める何かでなければなりません。私はJavaではそれほど良くはありませんが、Cではシグナルを使うことを意味します。
Javaで同等のものがあっても、信号を避けることをお勧めします。
より良い選択肢は、select()
(またはJava同等のもの)の呼び出しでthread1をブロックし、ソケットとパイプで待機することです。 Thread2はソケットを閉じるときにパイプに書き込み、thread1はselect()から戻り、thread2への応答をパイプに書き込んだり、select()をパイプでのみ呼び出す。 Thread2はその応答を読み取り、ソケットを閉じ、新しいソケットを開き、パイプの下に何か別のものを送ってthread1を再び起動させます。今度はselect()
に戻ることができますが、今回はパイプと新しいソケットで戻ります。これにより、thread1とthread2の間でランデブ実行が達成されます。 thread1がソケットを使用していないときに(パイプ通信を介して)知っているので、thread2は古いソケットを閉じて新しいソケットを開くことができます。
これはやや乱雑です。さらに、reactor
のデザインパターンのようになっています。どちらの場合でも、実行中のループの一部としてソケットを読み取るかどうかを選択するために、select()
を使用するスレッドを1つだけ持つこともできます。この単一スレッドは、利用可能なときにデータを読み取ることになり、データが到着することを期待してブロッキング読み取りを実行しません。ソケットの書き込みに何か問題が生じ、ソケットを交換する必要がある場合は、単純にそうします。他に同期するスレッドはありません。ソケットがネットワーク上のリモートサーバーに接続されていると仮定すると(同じマシン上のサービスではなく)、イーサネットの速度は支配的なボトルネックになります。原子炉スタイルのシステムはそれほど遅くはありません。
reactor
システムスタイルでは、ネットワーク障害を扱うのがはるかに簡単です。なぜなら、他のスレッドが不適切であると判断したアクションを実行するためのスレッドがないからです。残念ながら、ほとんどのプログラミング環境はproactor
です(Windows、Boost ASIO、RabbitMQなど)。何か問題が起こるまでは、Proactorシステムは問題ありません。その後、プログラマーにとっては非常に複雑になる可能性があるため、ボーク処理されたコールバックと非同期IOをすべて整理します。
可能な場合は、ZeroMQを使用することもできます。 ZeroMQをどこでも使用する必要がありますが(サーバも)、ネットワークの問題に対処するのがはるかに簡単です。これはリアクターであり、プロクターではありません。
これは「非同期」ではありません。これはマルチスレッドです。同じことではありません。 – EJP