0

私はサーバーと非同期で通信するSpring CLIアプリケーションを構築しました。サーバーは与えられた、私はそれを作成していない、基本的に私のアプリケーションは、TCPソケットを開いて、それを介してJSONを送信する必要がありますし、JSONを返します。 CLIパラメータを使用しないことが必須ですが、要求のコールバックでは、CLIに対応する番号を挿入して選択する必要があるオプションのセットをユーザーに表示します。コマンドを入力するとコンソールに表示される(これは予想される動作です)、何かを押すまで非同期コールバックをブロックします(何も表示されない場合はCLIに何も表示されません)。私が束を押していない限りコールバック - これは予期せぬことです)。コンソールから読み込むには、JLineのコマンドラインを使用しましたが、私が達成したいのは、サーバーからの応答を取得し、コールバックが提供されると、コールバックが実行されているスレッドにコンソールが与えられます。コールバックの内容を直ちにコンソールに出力し、何もせずに入力を読み取ることができます)。JavaのSpring CLIでの非同期IO処理方法は?

いくつかのコード:次に

public void runReceiver(){ 
    receiverThread = new Thread(() -> { 
     byte[] digit = null; 
     int nb; 
     Iterator<CommandListener> it; 
     CommandListener listener; 
     String message; 
     List<CommandListener> listenersToRemove = new ArrayList<>(); 
     while (true) { 
      try { 
       nb = communicatorInput.readInt(); 
       digit = new byte[nb]; 
       communicatorInput.readFully(digit); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      it = listeners.iterator(); 
      while (it.hasNext()){ 
       listener = it.next(); 

       if (digit != null && digit.length > 0) { 
        message = new String(digit); 
        // the message was not acknowledged 
        if(message.contains("NACK")){ 
         try { 
          listener.onError(message); 
          if (listener.isDone()) { 
           listenersToRemove.add(listener); 
          } 
         } catch (Exception e){ 
          e.printStackTrace(); 
         } 
        } else try { 
         listener.onCompleted(message); 
        } catch (InvalidObjectException e){ 
         Main.logger.debug(String.format("Response could not be parsed as %s", listener.getCommandType())); 
        } catch (Exception e){ 
         e.printStackTrace(); 
        } 

        if (listener.isDone()) { 
         listenersToRemove.add(listener); 
        } 
       } 
      } 
      listeners.removeAll(listenersToRemove); 
     } 
    }, "receiverThread"); 

    receiverThread.setDaemon(true); 
    receiverThread.start(); 

CLIコマンド(それがここには入力を想定していません):

@CliCommand(value="start", help = "Starts stuff") 
public void start() throws IOException, InterruptedException { 
    // this method is passed to the thread with the listener 
    getAvailabilities().updateAvailabilities("all", "all", "all", someListener); 
} 

そして、そのリスナーのためのコールバック:

someListener = new CommandListener() { 
      private String source = "Start some listener"; 
      @Override 
      public void onCompleted(String r) throws IOException { 
       System.out.println("Which would you like to start?"); 

       getAvailabilities().printAvailableBrands(); 

       String brandNumber = ""; 
       while(Objects.equals(brandNumber, "")){ 
        System.out.println("Please enter the number of the Brand: "); 
       //when the callback arrives here I still only see ">spring:" and I get nothing printed on the console 
        brandNumber = cr.readLine(); 
        if(!isInputAllowed(brandNumber, getAvailabilities().AvailableBrands.size())){ 
         brandNumber = ""; 
        } 
       } 
       BrandName = getAvailabilities().AvailableBrands.get(Integer.parseInt(brandNumber) - 1); 
       //updating the availabilities narrows down the things I list to the console, so I send an update after every selection 
       getAvailabilities().updateAvailabilities("all", BrandName, "all", getInterfaceListener); 
       done = true; 
      } 

これはわずかかもしれませんIdeaでCLIをデバッグしているときに、時には奇妙な入力を得るという問題につながります。 startを挿入するとNo such command as arと表示され、もう一度Enterキーを押すと残りの部分が表示されます(No such command as stt)。

答えて

0

問題はここにある:

if (listener.isDone()) { 
    listenersToRemove.add(listener); 
} 

あなたのリスナーが非同期に実行させたい場合は、それが最も可能性が高いfalseを返しますとあなたは同じスレッド上ですぐに自分の完了を確認するべきではありません。

あなたが持つかもしれない問題は、あなたのリスナーが、いくつかのタスクをスケジュールしますが、すぐにあなたのようにそれを終えるループの後にそれらを除去するための時間がないということである。

listeners.removeAll(listenersToRemove); 

あなたのロジックが何であるかを伝えることは非常に困難ですしかし、私は次の反復であなたのリストが空であると推測します。

関連する問題