Вход Jline прерван системой

У меня возникли некоторые проблемы с 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();
    }
}

Какие-либо решения?

0 ответов

Другие вопросы по тегам