PROBLEMA Stampare a schermo un certo prompt ogni nuova riga in java

Hero467

Utente Attivo
689
404
OS
I use ARCH btw
Sono 3 giorni che mi arrovello su questo problema. Ho interpellato Bard e ChatGPT fino allo sfinimento, e ho provato ogni situazione che mi veniva in mente.
Questi sono i codici
Java:
public void run() {
    while(true) {
        System.out.print(">>> ");
        System.out.flush();
            
        scanner = new Scanner(System.in);
        String command = scanner.nextLine();
        parseCommand(command, server);
    }
}
Java:
public void clientLoggedIn(String username, String ip) {
    String time = LocalTime.now().toString();

    System.out.println("\n[LOG] " + time + " - " + username + " logged in from " + ip);
}

Il primo snippet viene eseguito sul thread principale. È stato progettato per non ricevere input spesso, quindi si troverà frequentemente ad aspettare bloccato su scanner.nextLine().
Il secondo snippet viene eseguito su un altro thread e, come si può intuire, si occupa di stampare dei log. Vengono stampati sulla stessa console del prompt dell'altro codice, e decisamente più spesso.

Il problema è il seguente: se il programma è così>>> che aspetta un input, e l'altro metodo nell'altro thread vengono stampati dei log, mi ritroverei così:
Codice:
>>>
(log stampato)
(punto in cui effettivamente il prompt si aspetta un input)
.

Qualcuno sa come fare in modo di stampare >>> ogni nuova riga vuota? Così avrei il prompt che viene stampato di nuovo subito dopo un log
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Non sono sicuro di aver capito benissimo.

La prima idea che mi viene è usare la sincronizzazione e mantenere però il prompt in un thread separato. A quanto ricordo puoi usare i metodi wait() e notify() e giocare con quelli:

- quello del prompt al momento del risveglio (a seguito della notify() richiamata da quello che stampa i log) stampa il prompt e si mette in pausa ancora, richiamando wait()
- quello principale a seguito dell'elaborazione del comando, richiama il notify() per risvegliare il thread che stampa il prompt

Il concetto è che avrai un thread che sta attendendo su un lock e il notify che lo risveglia.

Un'altra cosa che puoi fare, venuta in mente ora, è usare una coda per la stampa di tutto: tutto ciò che il server deve stampare va nella coda invece di essere stampato immediatamente (un pò il classico Producer/Consumer). Ogni volta che la coda è vuota, viene stampato il prompt a video.

La seconda dipende ovviamente da quante cose devi toccare nel tuo codice... anche se la prima ti farà comunque modificare qualcosa.

EDIT:
Una cosa che non mi è chiara è se il comando che attendi in input influenza poi l'altro thread che stampa i log (diversificando magari il tipo di log stampato, tanto per dire).
 

Hero467

Utente Attivo
689
404
OS
I use ARCH btw
Ho seguito la seconda strategia che mi hai suggerito, comoda da implementare ma non esattamente quello che volevo.

EDIT:
Una cosa che non mi è chiara è se il comando che attendi in input influenza poi l'altro thread che stampa i log (diversificando magari il tipo di log stampato, tanto per dire).
No, i log non vengono influenzati dal comando atteso in input, è solo che se arriva un log mi sballa il prompt
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Penso che la soluzione migliore sia attraverso wait/notify.

C'è anche il taccone, quello che si fa a lavoro per fare le cose in corsa (specie in certi posti): aggiungere direttamente il prompt dove stampi i log.
 

Hero467

Utente Attivo
689
404
OS
I use ARCH btw
Puoi fornirmi un esempio concreto? Perché, pensandoci, il problema che ho resta: cioè che il primo metodo resta fermo a String command = scanner.nextLine(); e nel mentre l'altro thread può stampare cose.
Dove dovrei mettere il wait?
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Mi è un pò difficile scriverti un esempio, non sto avendo molto tempo.

La soluzione più semplice è che quando stampi il LOG inserisci anche ">>>" nel terminale. Non è una soluzione accettabile?

L'alternativa mi sa che è avere un thread dedicato che ti stampa ">>>", ma dovrai pur sempre farlo partire a seguito di un evento e fargli stampare quel prompt.
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!