系统输出中断Jline输入

时间:2018-02-11 13:48:48

标签: java console-application jline2

我在使用Jline方面遇到了一些麻烦,并且不太了解如何正确使用它,一切似乎都可以从示例中解决,但是当我尝试将其移动到我的控制台应用程序时,事情变得很奇怪。

我遇到过两个问题:

  1. 当您将输入写入控制台而其他内容通过System out记录消息时,写入的输入会被破坏。 (查看:https://i.imgur.com/ZAJDjTI.png

  2. 我试图将命令同步到主线程,因为读者线程将被阻塞,但这次你会发现这会导致输出文本接管命令输入空间。 ((绿色文字为输入,白色为输出)查看:https://i.imgur.com/CdKiIYy.png

  3. 我预期的输出是来自控制台底部的输入不受控制台输出的影响,在底部留下一个平滑的输入文本层。 (查看:https://i.imgur.com/HfH5l8U.png?1

    这是我写的一个示例类,用于演示我遇到的两个问题:

    import jline.console.ConsoleReader; 
    import java.io.IOException;
    import java.util.LinkedList;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Example {
    
        private ConsoleReader consoleReader;
        private LinkedList<Runnable> syncQueue = new LinkedList<>();
    
        private ReentrantLock lock = new ReentrantLock();
    
    
        public Example() {
            try {
                this.consoleReader = new ConsoleReader();
                this.consoleReader.setExpandEvents(false);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            //If you enable this, Jline seems to be disrupted by the System out.
            // startStopwatch();
            setupJline();
    
            //Ticker, its ugly i know
            while (true) {
    
                lock.lock();
                try {
                    while (syncQueue.size() > 0) {
                        Runnable runnable = syncQueue.poll();
                        try {
                            runnable.run();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                } finally {
                    lock.unlock();
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
        private void setupJline() {
            new Thread("Console Thread") {
                @Override
                public void run() {
                    while (true) {
                        try {
                            String line = consoleReader.readLine(">");
                            if (line != null && line.trim().length() > 0) {
                                //Lets pass this on as an instruction to our program
    
                                //Sync seems okay, output wise
                                handleInstructionSynced(line);
    
    
                                //async seems to mess things up though, comment the handleInstructionSynced method and
                                //uncomment the Async one to see what i mean.
    
                                //handleInstructionAsync(line);
                            }
                            consoleReader.flush();
    
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    
        //Just a dummy example instruction handler
        private void handleInstructionAsync(String input) {
            System.out.println("You've input \"" + input + "\" as your instruction.");
        }
    
        private void handleInstructionSynced(String input) {
            runSync(() -> System.out.println("You've input \"" + input + "\" as your instruction."));
        }
    
    
        private void runSync(Runnable runnable) {
            lock.lock();
            try {
                syncQueue.add(runnable);
            } finally {
                lock.unlock();
            }
        }
    
        private void startStopwatch() {
    
            Timer timer = new Timer();
            TimerTask timerTask = new TimerTask() {
                int time = 0;
    
                @Override
                public void run() {
                    System.out.println(time + " seconds counted");
    
                    time++;
                }
            };
            timer.scheduleAtFixedRate(timerTask, 0, 1000);
        }
    
        public static void main(String[] args) {
            new Example();
        }
    }
    

    任何解决方案?

0 个答案:

没有答案