Unterste Zeile der Java Konsole für Input reservieren?
Hallo!
Ich Arbeite grade an einem Java Programm welches Input über System.console().readLine() nimmt und dann in einem neuen Thread die Aufgabe startet, welche auf der Konsole loggt. Das Problem: Wenn ich am tippen bin für einen weiteren Befehl wird dieser zwar korrekt verarbeitet, aber er wird visuell auf der Konsole mit den Logs gemischt (siehe Bild)
Das Output sollte "Temperatur von Thermometer ID:..." sein, aber wie man beim zweiten Thermometer sehen kann, wurde ein Input von "ew" (ich habe nur auf meine Tastatur geklopft) mit dem Log gemischt. Es sollte allerdings so sein, wie z.B. bei Minecraft Servern, wo die Unterste Zeile der Konsole IMMER für Eingaben reserviert ist.
Danke!
2 Antworten
"Es kann nur einen geben"
...das gilt nicht nur für den Highlander, sondern (und vor allem) auch bei schreibenden Threads.
Multithreading erfordert einen hohen organisatorischen Aufwand, damit es keine Kollisionen gibt. Dein Output ist ein Zusammenstoß...
Dein Log-Thread schreibt munter in die System.Console und diese hat nur einen Schreibcursor, welcher (wenn nicht durch Positionierungsbefehle explizit gesteuert) einfach nur mit jedem Zeichen horizotal weiterrückt und bei einem Linefeed in die nächste Zeile wechselt. Mehr ist da nicht.
Jetzt hast Du aber einen 2. parallelen Thread der genau das gleiche tut. Wenn du etwas eingibst wird es an die aktuelle Position des Cursors "geechot".
Beide Threads wissen nichts voneinander , also schicken sie einfach ihre Zeichen an die Console und der ist es völlig Wumpe woher die Zeichen kommen. Die bringt alles wie es kommt auf den Bildschirm. Das Deine Eingegebenen Buchstaben gerade vorn gelandet sind, ist mehr oder weniger dem Umstand geschuldet, das Du langsamer tippst als der Log-Thread schreibt.
...wie z.B. bei Minecraft Servern, wo die Unterste Zeile der Konsole IMMER für Eingaben reserviert ist.
Dass ist eine ganz andere Sache. Derartige "Consolen" sind sind GUIs die aussehen wie "Console" oder echte Consoleanwendungen , die so ausgelegt sind, das das sie in Dauerschleife versuchen Zeichen einzeln lesen und an eine festgelegte Position schreiben. In der "Freizeit" zwischen den Leseoperationen ,kümmert sich die schleife um das Schreiben von gebufferten Daten anderer Threads/Prozesse. Damit ist sichergestellt, das nur einer sich um das Schreiben (und die Cursorpositionierung) kümmert.
Parallele Prozesse legen ihre "Schreibwünsche" in einen "Briefkasten" (FIFO-Buffer)
Wenn ich Dir so ein Ding schreiben würde wäre das wohl eher eine "Fred Feuerstein"-Nummer und wir wollen ja nicht in Richtung Steinzeit.
Die einfachere Variante wäre ein Ereignisgesteuertes GUI ( wenn man möcht kann man ja den Hintergrund Schwarz machen und die Schrift Weiß... dann siehts nach Console aus, hat aber die volle Funktionalität einer GUI. Damit musst Du lediglich um das Layout kümmern und dem für den Output zuständigen Textfeld per Event mitteilen, dass neue Daten hat und wo diese abzuholen sind...
- https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
- https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html
oder
Da musste ich tatsächlich mal ChatGPT anschmeißen. Versuche mal das:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Thread inputThread = new Thread(() -> {
while (true) {
String input = scanner.nextLine();
// hier können Sie die Eingabe verarbeiten
}
});
Thread logThread = new Thread(() -> {
while (true) {
// hier können Sie das Ausgabe-Logging durchführen
System.out.println("Temperatur von Thermometer ID:...");
}
});
inputThread.start();
logThread.start();
}
}
In diesem Beispiel liest der Thread
inputThread
die Eingabezeilen über einen
Scanner
ein, während der Thread
logThread
die Ausgabezeilen auf die Konsole schreibt. Da diese Threads getrennt ausgeführt werden, sollten die Ein- und Ausgabeaufforderungen in getrennten Zeilen angezeigt werden.
In C# kann man mit lock() die Konsole einfach sperren und so den Input des Users erlauben und verschiedene Loggingtools davon abhalten, sich nicht zu vermischen. Vielleicht hilft die Lösung von ChatGPT schon weiter?