2010-05-04 11 views
10

Posso capire perché le app di rete utilizzano il multiplexing (per non creare troppi thread) e perché i programmi utilizzano chiamate asincrone per il pipelining (più efficiente). Ma non capisco lo scopo di efficienza di AsynchronousFileChannel.Perché utilizzare AsynchronousFileChannel di Java?

Qualche idea?

risposta

7

È un canale che è possibile utilizzare per leggere i file in modo asincrono, ovvero le operazioni di I/O vengono eseguite su un thread separato, in modo che il thread da cui viene chiamato possa eseguire altre operazioni mentre le operazioni di I/O sono accadendo.

Ad esempio: I metodi read() della classe restituiscono un oggetto Future per ottenere il risultato della lettura dei dati dal file. Quindi, ciò che puoi fare è chiamare read(), che verrà restituito immediatamente con un oggetto Future. In background, un altro thread leggerà i dati effettivi dal file. Il tuo thread può continuare a fare le cose e quando ha bisogno dei dati letti, chiami get() sull'oggetto Future. Ciò restituirà quindi i dati (se il thread in background non ha completato la lettura dei dati, renderà il blocco del thread finché i dati non saranno pronti). Il vantaggio di questo è che il thread non deve attendere l'intera durata dell'operazione di lettura; può fare altre cose finché non ha davvero bisogno dei dati.

Vedere the documentation.

Si noti che AsynchronousFileChannel sarà una nuova classe in Java SE 7, che non è ancora stata rilasciata.

+0

Grazie, ma mi chiedevo di più sulle ragioni di efficienza - non riesco a vedere il motivo per cui eseguire l'I/O in un altro thread aiuta. Un thread deve sempre bloccare l'I/O, e non vi è alcun riutilizzo delle risorse, utilizzo delle funzionalità hardware o altri comportamenti che migliorano le prestazioni. –

+9

Il vantaggio di questo è che * non * necessita di due thread. Se si sta scrivendo un grande blob di dati, a livello basso, il controller del disco esegue il processo di scrittura dei dati sul disco prima di segnalare un interrupt che sale nello stack per richiamare il gestore di completamento. Durante questa procedura il thread non deve essere bloccato e può fare altre cose. Si utilizza un thread in meno, lo scheduler dei thread gestisce un thread in meno, non è necessario utilizzare java notify. Fondamentalmente, si utilizzano meno risorse per fare la stessa cosa. – lenkite

+2

Il sistema operativo può anche ottimizzare l'ordine in cui vengono eseguite operazioni IO asincrone. Ad esempio, se si dispone di un numero elevato di letture di una varietà di regioni in un file eseguite in modo asincrono, il sistema operativo può raggrupparle in letture sequenziali, senza doversi preoccupare dell'esecuzione di tutte le operazioni nell'ordine specificato. –

3

Mi sono appena imbattuto in un altro motivo in qualche modo inatteso per l'utilizzo di AsynchronousFileChannel. Quando si eseguono scritture casuali orientate ai record su file di grandi dimensioni (che superano la memoria fisica e quindi la cache non aiuta tutto) su NTFS, trovo che AsynchronousFileChannel esegue più di due operazioni, in modalità single-thread, rispetto a un normale FileChannel.

La mia ipotesi migliore è che poiché l'io asincrono si riduce all'IO sovrapposto in Windows 7, il driver del file system NTFS è in grado di aggiornare le proprie strutture interne più rapidamente quando non deve creare un punto di sincronizzazione dopo ogni chiamata .

I micro-confrontata RandomAccessFile per vedere come sarebbe eseguire (risultati sono molto vicino a FileChannel, e ancora metà della performance di AsynchronousFileChannel.

Non so cosa succede con multi-thread scrive. Questo inizia Java 7, su un SSD (l'SSD è un ordine di grandezza più veloce del magnetico e un altro ordine di grandezza più veloce su file più piccoli che si adattano alla memoria)

Sarà interessante vedere se gli stessi rapporti valgono su Linux.

+0

Infatti, a patto che i file siano corti per adattarsi alla cache del sistema operativo, l'I/O viene completato immediatamente indipendentemente dal fatto che l'I/O sia sincrono o meno. Vorrei solo aggiungere che otterrete 2x speedup max quando il vostro I/O e il calcolo sono di lunghezza comparabile. Se il calcolo è solo una piccola frazione del tempo di I/O o I/O è trascurabilmente più corto del calcolo, allora non è nemmeno logico sovrapporsi. – Val

3

Il motivo principale per cui posso pensare di utilizzare l'I/O asincrono è quello di migliorare utilizzare il processore. Immagina di avere qualche applicazione che fa una sorta di elaborazione su un file. Inoltre, supponiamo di poter elaborare i dati contenuti nel file in blocchi. Se non utilizzi l'I/O asincrono, la tua applicazione probabilmente si comporterà in questo modo:

  1. Leggere un blocco di dati. Nessun utilizzo del processore a questo punto mentre sei bloccato in attesa che i dati vengano letti.
  2. elaborare i dati appena letti. A questo punto l'applicazione inizierà a consumare cicli della CPU man mano che elabora i dati.
  3. Se più dati da leggere, vai a # 1.

L'utilizzo del processore salirà e quindi a zero e poi su e poi a zero, .... Idealmente non vuoi essere inattivo se vuoi che la tua applicazione sia efficiente e processa i dati il ​​più velocemente possibile. Un approccio migliore potrebbe essere:

  1. asincrone Problema leggere
  2. Quando lettura completa prossimo numero asincrona leggere e poi elaborare i dati

Il primo passo è il bootstrap. Non hai ancora dati quindi devi emettere una lettura. Da quel momento in poi, una volta ricevuta la notifica, una lettura è stata completata, emetterai un'altra lettura asincrona e poi elaborerai i dati. Il vantaggio qui è che, una volta terminata l'elaborazione del blocco dei dati, la prossima lettura è probabilmente finita, quindi i dati sono sempre disponibili per essere elaborati e quindi si utilizza in modo più efficiente il processore. Se l'elaborazione termina prima della fine della lettura, potrebbe essere necessario eseguire più letture asincrone in modo da avere più dati da elaborare.

Nick

0

Ecco qualcosa che nessuno ha menzionato: FileChannel, dal momento che implementa InterruptibleChannel, così come tutto ciò che lo utilizzano come la OutputStream restituito da Files.newOutputStream(), ha lo sfortunato [1] [2] immobili che qualsiasi operazione di blocco che esegue (ad esempio read() e write()) da un thread in interrupted state causerà la chiusura dello Channel con java.nio.channels.ClosedByInterruptException.

Per i casi in cui questo è un problema, utilizzare AsynchronousFileChannel è invece un modo possibile per creare una soluzione.

Problemi correlati