2013-07-26 10 views
7

In questo codice java,qual è l'esatto ordine di esecuzione per provare, prendere e, infine?

import java.io.IOException; 

public class Copy 
{ 
    public static void main(String[] args) 
    { 
     if (args.length != 2) 
     { 
     System.err.println("usage: java Copy srcFile dstFile"); 
     return; 
     } 

     int fileHandleSrc = 0; 
     int fileHandleDst = 1; 
     try 
     { 
     fileHandleSrc = open(args[0]); 
     fileHandleDst = create(args[1]); 
     copy(fileHandleSrc, fileHandleDst); 
     } 
     catch (IOException ioe) 
     { 
     System.err.println("I/O error: " + ioe.getMessage()); 
     return; 
     } 
     finally 
     { 
     close(fileHandleSrc); 
     close(fileHandleDst); 
     } 
    } 

    static int open(String filename) 
    { 
     return 1; // Assume that filename is mapped to integer. 
    } 

    static int create(String filename) 
    { 
     return 2; // Assume that filename is mapped to integer. 
    } 

    static void close(int fileHandle) 
    { 
     System.out.println("closing file: " + fileHandle); 
    } 

    static void copy(int fileHandleSrc, int fileHandleDst) throws IOException 
    { 
     System.out.println("copying file " + fileHandleSrc + " to file " + 
         fileHandleDst); 
     if (Math.random() < 0.5) 
     throw new IOException("unable to copy file"); 

     System.out.println("After exception"); 
    } 
} 

l'output che mi aspetto è

copying file 1 to file 2 
I/O error: unable to copy file 
closing file: 1 
closing file: 2 

Tuttavia a volte ottengo questo output previsto e altre volte ottengo il seguente output:

copying file 1 to file 2 
closing file: 1 
closing file: 2 
I/O error: unable to copy file 

ea volte anche questa uscita:

I/O error: unable to copy file 
copying file 1 to file 2 
closing file: 1 
closing file: 2 

e se ottengo la prima, seconda o terza uscita sembra accadere casualmente durante ogni esecuzione. Ho trovato THIS POST che sembra parlare dello stesso problema, ma ancora non capisco perché a volte ottengo l'output 1, 2 o 3. Se capisco correttamente questo codice, l'output 1 dovrebbe essere quello che ottengo ogni volta (si verifica l'eccezione) . Come faccio a essere sicuro di ottenere l'output 1 in modo coerente, o di essere in grado di dire quando riceverò l'output 1 o quando riceverò l'output 2 o 3 per ?

+0

possibile duplicato del [ordine di stampa a caso per System.out & System.err chiamate] (http://stackoverflow.com/questions/12594537/ random-printing-order-for-system-out-system-err-calls) – user93353

risposta

16

Il problema è che si sta scrivendo un output su System.out e alcuni su System.err. Questi sono flussi indipendenti, con buffering indipendente. Il momento in cui vengono scaricati è, per quanto ne so, non specificato.

Il breve è che quando si scrive su flussi diversi, non è possibile utilizzare l'ordine in cui viene visualizzato l'output per determinare l'ordine in cui si sono verificate le chiamate a println(). Si noti che l'output su System.out appare sempre nell'ordine previsto.

Per quanto riguarda l'ordine di esecuzione, il corpo di try viene eseguito per primo. Se lancia un'eccezione, viene eseguito il corpo della clausola catch appropriata. Il blocco finally viene sempre eseguito per ultimo.

+0

ma in teoria, l'ordine dovrebbe essere quello mostrato nell'output 1 non dovrebbe? – user13267

+1

@ user13267 - Sì. L'ordine di esecuzione è specificato e corrisponde all'ordine previsto per l'output. Fai in modo che tutto vada a un singolo flusso (ad esempio, 'System.out') e dovresti vedere ogni volta l'ordine previsto. In alternativa, chiama 'flush()' su ogni flusso di output immediatamente dopo ogni volta che scrivi su di esso. Questo dovrebbe anche correggere l'ordine in cui l'output appare sulla console. –

+0

Ho provato 'System.out.flush()' e 'System.err.flush()' ogni volta che sono stati chiamati, ma l'ordine di uscita rimane lo stesso. – user13267

2

La cosa con la gestione delle eccezioni utilizzando try catch block è che il controllo andrà a provare se qualche eccezione si otterrà all'interno del catch block. Ma il controllo andrà al blocco finale ogni volta che esegue.

1

Si sta scrivendo il messaggio di errore sia su stdout che su stderr. Hanno diversi buffer, quindi non c'è alcuna garanzia che l'output che vedete sarà nello stesso ordine in cui è stato creato, tra i due flussi di output.

Dal momento vedo errori nel codice (anche se il superfluo return; nel vostro catch segmento bloccato nella mia Craw un po '), vorrei suggerire che si scrive tutti i messaggi per stderr, e vedere se l'ordine messaggio è un po 'più in linea con quello che ti aspettavi.

1

Hai un problema tecnico nell'esempio che vorrei rimuovere. Stai scrivendo su System.out e System.err e aspetta la tua console per sincronizzare correttamente entrambi gli stream. Per rimuovere gli effetti collaterali vorrei solo utilizzare un flusso qui.

3

Prima esecuzione Try blocco se è successo finalmente eseguirà, se try blocco fallisce, allora catch eseguirà e finally eseguire. Che cosa mai accadrà, il blocco verrà eseguito.

Ma

Se si chiama System.exit(0) finalmente non blocco eseguito

+0

Che cosa accadrà alla fine il blocco verrà eseguito non accetterò che cosa succederebbe se si chiamasse System.exit()? –

+0

@Sunny si hai ragione, ma sto parlando solo di questo caso. Se si chiama System.exit (0) nel tentativo. Oppure crea qualcosa che faccia sì che la JVM si chiuda o si blocchi (come in un deadlock). Altrimenti, no. –

Problemi correlati