Вход Jline прерван системой
У меня возникли некоторые проблемы с Jline, и я не совсем понимаю, как это правильно работать, кажется, что все работает на примерах, но когда я пытаюсь переместить его в консольное приложение, все становится странным.
Я столкнулся с двумя проблемами:
Когда вы записываете ввод в консоль, в то время как что-то еще записывает сообщение через System out, записанный ввод прерывается. (Просмотр: https://i.imgur.com/ZAJDjTI.png)
Я попытался синхронизировать команды с основным потоком, поскольку поток чтения будет блокироваться, но на этот раз вы обнаружите, что это приводит к тому, что выходной текст занимает пространство ввода команд. ((Зеленый текст - это ввод, белый - это выход). Просмотр: 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();
}
}
Какие-либо решения?