2013-02-28 11 views
12

perche questo codice java:Race tra lo System.out e System.err in java

public class CMain { 
    public static void main(String[] args){ 

     for (int i = 0; i < 10; i++) { 
      System.out.println("A"); 
      System.err.println("B"); 
     } 

    } 
} 

da un rapido sguardo al codice, alcuni di noi possono pensare l'uscita deve essere la stampa di As e Bs in alternativa. Tuttavia non lo è! È un'apparizione casuale di 10 caratteri A e 10 B. Qualcosa di simile a questo:

enter image description here

Perché? e qual è la soluzione per far sì che gli As e Bs vengano visualizzati alternativamente (A B A B A B ...) Prima di porre questa domanda, ho controllato diverse altre domande simili per la soluzione e non funzionanti per il mio caso! Ho portato alcuni di loro qui:

+5

Quelli sono due diversi flussi che capita di essere uniti nella stessa console. Se vuoi tutto in un unico posto e in un dato ordine, perché non usi un singolo stream (fuori O err)? –

+0

Penso che la risposta sia nel tuo secondo link "Il problema è che è responsabilità dell'emulatore di terminale (nel tuo caso, Eclipse) elaborare l'output standard e l'errore standard dell'applicazione, senza comunicare con l'emulatore di terminale non si può mai essere certi che i messaggi errati vengano visualizzati nell'ordine corretto, pertanto, prenderei in considerazione la possibilità di stampare tutto su err e di reindirizzare il file su un file. È comunque possibile utilizzarlo per un'interazione utente pulita." – KevinDTimm

+1

Entrambi gli stream sono sincronizzati, ma non sullo stesso lock, quindi dovresti aspettarti qualche interleaving ... Comunque, ogni stream, individualmente, sarà ordinato. – assylias

risposta

0

Poiché ci sono due flussi separati, l'output che si sta dando è possibile.

+0

A seconda del sistema, sia 'System.out' che' System.err' vengono svuotati automaticamente per impostazione predefinita. È un'eclissi che non rileva l'ordine in cui vengono scritti byte o caratteri. Sono necessariamente in ordine poiché 'println()' dovrebbe restituire * solo * dopo * lo scarico del flusso. –

+0

hai ragione, sono totalmente d'accordo con te. Questo è il motivo per cui l'ordine di A/B è possibile. Ci può essere qualsiasi ordine anche. –

9
Why does this happen? 

Questo perché out e err sono due flussi di uscita differenti. Tuttavia, entrambi stampano su console. Quindi non li vedi come flussi diversi. Inoltre, quando si esegue out.println(), non è garantito che si vedrà l'output sulla console non appena viene eseguita l'istruzione. Invece, le stringhe sono di solito (dipende dal sistema) memorizzate in un buffer di output (se lo si desidera) che viene elaborato successivamente dal sistema per mettere l'output dal buffer sullo schermo.

Solution :(

Anche se, come Eng.Fouad ha sottolineato che è possibile utilizzare setOut(System.err) o setErr(System.out) per farli ordinati, non vorrei ancora suggerisco di fare che, quando in realtà si sta mettendo questo in un'applicazione (uso solo per scopi di debug).

Ciò che la soluzione proposta fa è che finirà per utilizzare un solo flusso sia per lo standard output che per l'errore standard, che non credo sia una buona cosa da fare.

+1

Immagino che dipenda dal sistema, Ankit ... –

+1

@owlstead yes (presumo che tu stia parlando del buffering) – Ankit

5

Sono diversi OutputStream s. Se si ha realmente bisogno per garantire l'ordine di stamparli, utilizzare:

System.setErr(System.out); 

o

System.setOut(System.err); 
+6

Questo probabilmente funzionerebbe, ma potresti perdere l'evidenziazione applicata da Eclipse. –

+0

@owlstead +1 sì. –

+0

@owlstead Si tratta esattamente della sostituzione di System.err.println ("B"); con System.out.println ("B"); –