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); 

这是很难告诉你的逻辑是什么但我想在下一次迭代时,你的列表是空的。