0

我已經構建了一個以異步方式與服務器通信的Spring CLI應用程序。服務器是給定的,我沒有創建它,基本上我的應用程序需要打開一個TCP套接字並通過它發送JSON,然後它發回一個JSON。強制不使用CLI參數,而是在請求的回調中,我想通過在CLI上插入相應的編號來向用戶顯示一組需要選擇的選項。很可能我沒有做正確的事情,因爲在輸入命令後,我在控制檯上看到spring>(這是一個預期的行爲),並且它將阻止異步回調,除非我按下某些內容(當我收到時沒有任何內容被打印到CLI除非我按下一堆輸入 - 這是意想不到的)。爲了從控制檯讀取到目前爲止我使用的JLine的命令行,我想實現的是當我從服務器獲得響應並且回調被提供時,控制檯被賦予正在運行回調的線程(I即時將回調的內容打印到控制檯,並且我可以在沒有任何技巧的情況下讀取輸入內容)。在Spring CLI中使用Java進行異步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,如果我再次按下輸入,它會說(其中一些)其餘的:No such command as stt

回答

0

的問題是在這裏:

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

如果要執行你的聽衆異步你不應該檢查自己的完成就在同一個線程,因爲它很可能會返回false。

,你可能會遇到的問題是,你的聽衆安排一些任務,但已經沒有時間立即結束它,你的循環之後將其刪除:

listeners.removeAll(listenersToRemove); 

這是很難告訴你的邏輯是什麼但我想在下一次迭代時,你的列表是空的。