2010-02-12 6 views
7

Sto lavorando su un MUD in Java. Ho letto Ingresso giocatore ogni tick, ma sto usando Scanner che utilizza le operazioni di blocco. Voglio avere input non bloccanti.Concurrent/non-blocking console input da tastiera

Ho guardato il pacchetto nio, che ha una classe Selector, ma non sono sicuro di come usarlo per quanto riguarda System.in. Immagino che ne avrò sicuramente bisogno una volta che avrò un server, ma per ora tutto è offline.

Ho provato ad estendere la classe principale da Applet e ignorando keyDown, ma ciò significava che l'input non era più accettato dopo il primo. Certo, non stavo più bloccando nulla, ma poi non c'era più alcun input. keyDown non mi hanno mai più chiamato, immagino.

Forse i thread possono essere interrotti anche quando stanno eseguendo operazioni di blocco?

Grazie per qualsiasi comprensione di questo problema.

+0

non bloccanti (networking) non sono fatte allo stesso modo non bloccante IO, almeno non nella maggior ambienti. – Textmode

risposta

2

Non è possibile farlo con la console di sistema perché ormai non è possibile eseguirlo in modalità multipiattaforma.

È possibile utilizzare la finestra mobile come console o trovare un approccio basato su JNI, ma potrebbe non funzionare su alcune piattaforme.

È possibile utilizzare JCurses. Potrebbe funzionare, è basato su JNI e supporta Windows e Linux.

+0

JCurses è costruito su UNIX 'curses' quindi sarà sicuramente il lavoro. – H2ONaCl

+0

A partire dal 2014/05/23, il collegamento 'explanation' è morto (ora collega alla pagina di parcheggio di dominio). – daveloyall

+0

@daveloyall L'ho rimosso. Grazie. – aalku

0

keyDown() è deprecated così io suggerirei di usare processKeyEvent e keyListener invece.

Forse i thread possono essere interrotti anche quando stanno eseguendo operazioni di blocco?

Sì, se si dispone di un riferimento all'oggetto thread che si desidera interrompere, è sufficiente chiamare il metodo interrupt() in tale istanza. E nel metodo run del thread puoi gestire l'eccezione interrotta. Tuttavia, questo sembra un po 'hack-ish. Non vedo come questo sia più utile dell'utilizzo di un semplice KeyListener.

+0

Thread.interrupt() imposta solo il flag di interrupt e riattiva il thread se sta dormendo o è bloccato. Non interrompe il normale file di blocco IO della lettura del socket. Inoltre, non interromperà un calcolo pesante o uno spinlock: il tuo codice deve controllare e obbedire al flag "interrotto" per poter essere interrotto. – ddimitrov

-1

avessi dovuto risolvere il problema simile con il blocco di scrittura/lettura da http. In quel caso particolare ho usato il buffer locale e i thread.

L'idea è semplice, una discussione legge dallo stdin e inserisce il contenuto nel buffer. Il secondo fa lo stesso con la scrittura.

E quindi si utilizzano query non bloccanti nel buffer.

codice di esempio:

class NonBlockingReader implements Runnable{ 
    Reader in; 
    List buffer; 
    public void run(){ 
    String line=null; 
    while((line=in.readLine())!=null){ 
     storeLine(line); 
    } 
    } 
    private synchronized storeLine(String line){ 
    buffer.add(line); 
    } 
    public synchronized String getLine(){ 
    if(list.size()>0) 
     return list.removeFirst(); 
    return null; 
    } 
} 

// .. same for writer, then you jast pass stdin and stdout ... 
+0

il flusso System.in, che è l'equivalente stdin di Java, viene memorizzato nel buffer, quindi l'app non vede i caratteri finché l'utente non preme Invio. – ddimitrov