0

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

我遇到了两个问题:

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

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

我期望的输出是来自控制台底部的输入不受控制台输出的影响,在底部留下一个平滑的输入文本层。(查看: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();
    }
}

有什么解决办法吗?

4

0 回答 0