2012-05-14 7 views
7

Ho molti thread che contemporaneamente leggono lo stesso file (interamente circa 100M) e solo un thread per aggiornare il file. Voglio mappare il file in memoria per ridurre FILE I/O. Come può essere fatto in Java?Come implementare la lettura simultanea in un file mappato alla memoria in Java?

io fondamentalmente hanno considerato i seguenti 2 metodi:

  1. con matrice di byte per memorizzare il file, e ogni volta creare ByteArrayInputStream di leggere il buffer quando multi-thread lettura.
  2. con NIO per ottenere un canale di file, sincronizzato il canale da leggere da MappedByteBuffer per la lettura multi-thread.

Non sono sicuro se i metodi dovrebbero funzionare. Si prega di aiutare a dare qualche suggerimento se c'è una soluzione migliore.

+0

Se tutti stanno leggendo e nessuno sta scrivendo, non è necessaria la sincronizzazione. – EJP

+0

@EJP ci sarà un thread da scrivere, tutti gli altri thread letti, preferisco usare ReadWriteLock su byte [] per farlo ora. –

+0

Grazie, ma, con rispetto, la tua domanda non menziona gli scrittori. Cambia completamente l'immagine. Ti suggerisco di modificare questo fatto critico nella tua domanda. – EJP

risposta

12

Utilizzare NIO con ogni thread che crea la propria mappatura e legge i dati nel proprio buffer privato. Mantenere la dimensione del buffer privato ottimale. Il sistema operativo legge il file nella sua cache di file nelle pagine e le pagine vengono lette nei buffer privati. Se le stesse regioni vengono lette da più thread, i dati verrebbero letti dalle stesse pagine nella cache dei file, salvando alcuni cicli di i/o di file. Di seguito è riportato un piccolo diagramma per indicare questo. Spero che aiuti a capire meglio.

memory mapped file io

Con riferimento allo schema sopra, sotto è una spiegazione. Una regione del file è mappata alla memoria. La creazione di una mappatura è solo un segno logico per dire che vuoi leggere da una particolare porzione di un file. Una volta creata la mappatura, la regione mappata è pronta per essere letta. Quando inizi a leggere, il sistema operativo recupera i dati del file nelle sue pagine nella cache dei file. La regione potrebbe essere associata a una o più pagine. Ora leggi le pagine nel tuo buffer privato (più pagine alla volta per ottimizzare). Qualche altro thread potrebbe leggere la stessa regione del primo, quindi legge anche le stesse pagine nel suo buffer privato. Si noti che questa volta la lettura avviene dalla cache dei file senza errori di pagina. Dopo aver elaborato il buffer privato, si richiede di leggere ulteriormente. Nota che stai leggendo una porzione del tuo mapping nel tuo buffer privato alla volta. Il tuo file potrebbe essere 100 MB e mappare una porzione da 10 MB in memoria; e tu hai un buffer privato di 40KB e prima leggi 40KB su 10MB. Quindi richiedi i prossimi 40 KB e così via. Il sistema operativo verifica se i dati che vuoi leggere sono già scaricati nella cache. In caso contrario, si verifica un errore di pagina e il sistema operativo recupera i dati richiesti nelle pagine. Anche in questo caso questi dati possono essere condivisi se più richieste di thread leggono la stessa regione. Puoi benissimo usare la cache dei file per leggere invece di creare il tuo buffer privato. Ma questo può portare a più errori di pagina se il file viene letto simultaneamente più volte su più regioni. Quindi in questo caso è meglio avere un buffer privato di dimensioni ottimali.

+0

Ciao Vikas, potresti spiegarmi con più dettagli? Sono molto nuovo a NIO. –

+0

@Grace Ho messo un diagramma per mostrare come funziona. Fare riferimento agli esempi di file di memoria mappati disponibili sul Web. – Drona

+0

Grazie per la spiegazione più dettagliata. Nel mio caso, avrò un file di circa 100 M, e circa 10000 clienti che hanno tutti bisogno di leggere l'intero file. Quindi al massimo avrò bisogno di 10000 thread, ogni thread ha bisogno di un buffer privato come 100M? Mi chiedo se l'utilizzo totale della memoria sia troppo alto? –