我在使用 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();
}
}
有什么解决办法吗?