1

現在、マシンと通信するアプリケーションを実装しようとしていますが、基本的に次のように動作するはずです。

  • プログラムはサーバーにメッセージを送信します (この場合、ファイルの最初の 255 バイト)。
  • マシンは、「メッセージを正常に受信しました」または「メッセージを受信できませんでした」という応答で応答します。
  • 次に、プログラムは、マシンの応答に応じて、次のメッセージ (次の 255 バイト) を送信するかどうか (最後のメッセージのエラー、最初からやり直す必要がある) を決定する必要があります。
  • プログラムが送信する必要がある各メッセージについても同様です (ファイルのサイズによって異なります)。

そのため、送信を行うスレッドと受信を行う別のスレッドを用意することを考えました。これは、マシンからメッセージを受信するクラスとしてクラスを登録するための API (インターフェイスを実装するだけで) と、そのためのメソッドがあるためです。マシンへのメッセージ送信はブロッキング タイプではないため、応答が到着した後にプログラムが何をすべきかを決定できるように、マシンの応答を待つ方法が必要です。

したがって、これら 2 つのスレッドを何らかの形で同期させる必要がありました。交換するメッセージの数を特定できるため、CyclicBarrier を試す必要がありました。これは、CyclicBarrier がこの問題の解決に役立つかどうかをテストするためのコードです (プログラムは実際にはマシンとの通信にソケットを使用しません。これはバリアをテストするためだけのものです)。

import java.io.*;
import java.net.*;
import java.util.concurrent.*;

public class BlockingTest{
  private CyclicBarrier barrier;

  class Receiver implements Runnable{
    @Override public void run(){
      try{
        ServerSocket ss = new ServerSocket(8080);
        while(!barrier.isBroken()){
          System.out.println("Waiting message...");
          Socket response = ss.accept();
          BufferedReader br = new BufferedReader(new InputStreamReader(
              response.getInputStream()));
          System.out.printf("Received: %s\n", br.readLine());
          barrier.await();
        }
      }catch(InterruptedException | BrokenBarrierException |
        IOException ex){
        System.err.println(ex.getMessage());
      }
    }
  }

  public BlockingTest(){
    this.barrier = new CyclicBarrier(2, new Runnable(){
      @Override public void run(){
        System.out.println("done.");
      }
    });

    new Thread(new Receiver()).start();

    try{
      Socket sender = new Socket("localhost", 8080);
      PrintWriter pw = new PrintWriter(sender.getOutputStream(), true);
      for(int i = 0; i < 3; i++){
        System.out.println("Sending message:");
        pw.println("Message!");
        this.barrier.await();
      }
    }catch(InterruptedException | BrokenBarrierException | IOException ex){
      System.err.println(ex.getMessage());
    }
  }

  public static void main(String[] arg){
    new BlockingTest();
  }
}

メッセージを 1 つだけ送信した場合 (BlockingTest() コンストラクターで for ブロックを送信せず、メッセージを送信するだけ)、このコードは期待どおりに機能しますが、for ブロックを追加すると、期待どおりに機能しません。最初にのみ機能し、その後ハングします。

Waiting message...
Sending message:
Received: Message!
done.
Waiting message...
Sending message:

質問は次のとおりです。

  • バリアを再利用可能にする方法は?それは自動ですか、それとも手動で行う必要がありますか?

  • ソケット (またはバリア コー​​ド) で見逃したことが原因で、プログラムがハングしていませんか?

4

1 に答える 1