簡體   English   中英

使用Java在Spring CLI中進行異步IO處理

[英]Async IO handling in Spring CLI with Java how to?

我已經構建了一個Spring CLI應用程序,該應用程序以異步方式與服務器通信。 服務器是給定的,我沒有創建它,基本上我的應用程序需要打開TCP套接字並通過它發送JSON,然后將它發送回JSON。 強制不使用CLI參數,而是在請求的回調中,我想向用戶顯示一組選項,他需要通過在CLI上插入相應的編號來選擇該選項。 很有可能我沒有做正確的事情,因為輸入命令后,我在控制台上看到spring> (這是預期的行為),除非我按一下(否則當我未打印任何內容時,它將阻塞異步回調)除非我按了許多回車鍵,否則接收回調,這是意外的)。 到目前為止,要從控制台讀取信息,我使用了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();

然后是一個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

問題在這里:

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

如果希望異步執行偵聽器,則不應立即在同一線程上檢查偵聽器的完成,因為它很可能會返回false。

您可能遇到的問題是,偵聽器安排了一些任務,但沒有時間完成任務,因為您在循環后立即將其刪除:

listeners.removeAll(listenersToRemove);

很難說出您的邏輯是什么,但是我想在接下來的迭代中您的列表為空。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM