SpringCLI中使用Java的异步IO处理如何?

SpringCLI中使用Java的异步IO处理如何?,java,callback,command-line-interface,user-input,spring-shell,Java,Callback,Command Line Interface,User Input,Spring Shell,我构建了一个SpringCLI应用程序,它以异步方式与服务器通信。服务器是给定的,我没有创建它,基本上我的应用程序需要打开一个TCP套接字并通过它发送一个JSON,然后它返回一个JSON。必须不使用CLI参数,而是在请求的回调中,我想向用户显示一组选项,用户需要通过在CLI上插入相应的数字来选择这些选项。很可能我没有做正确的事情,因为在输入命令后,我在控制台上看到spring>(这是一种预期的行为),它将阻止异步回调,除非我按下某个键(当我收到回调时,除非我按下一组回车键,否则不会向CLI打印任

我构建了一个SpringCLI应用程序,它以异步方式与服务器通信。服务器是给定的,我没有创建它,基本上我的应用程序需要打开一个TCP套接字并通过它发送一个JSON,然后它返回一个JSON。必须不使用CLI参数,而是在请求的回调中,我想向用户显示一组选项,用户需要通过在CLI上插入相应的数字来选择这些选项。很可能我没有做正确的事情,因为在输入命令后,我在控制台上看到
spring>
(这是一种预期的行为),它将阻止异步回调,除非我按下某个键(当我收到回调时,除非我按下一组回车键,否则不会向CLI打印任何内容-这是意外的)。到目前为止,为了从控制台读取数据,我使用了JLine的命令行,我希望实现的是,当我从服务器获得响应并提供回调时,控制台被提供给运行回调的线程(我立即将回调的内容打印到控制台,并且我能够无需任何技巧地读取输入)

一些代码:

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();
以及该侦听器的回调:

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
时,它会说
没有类似ar的命令,如果我再次按enter键,它会说(部分)其他命令:
没有类似stt的命令
问题在于:

if (listener.isDone()) {
    listenersToRemove.add(listener);
}
如果希望侦听器异步执行,则不应立即在同一线程上检查它们的完成情况,因为它很可能返回false

您可能遇到的问题是,您的侦听器安排了一些任务,但没有时间完成,因为您在循环结束后立即将其删除:

listeners.removeAll(listenersToRemove);
很难判断您的逻辑是什么,但我猜在下一次迭代中,您的列表是空的

listeners.removeAll(listenersToRemove);