2012-12-20 5 views
6

Quindi sto provando a scrivere messaggi da utenti su una rete di messaggistica su un file. Sto provando a costruire questo programma con buone pratiche java e una tecnica di file IO appropriata.È consigliabile archiviare un sacco di testo che viene acquisito periodicamente in una cache prima di salvarlo in un file?

Attualmente il mio programma riconosce che qualcuno ha pubblicato un messaggio, prende il messaggio e lo scrive immediatamente in un file. Creare l'oggetto file, creare l'oggetto writer, accodare il messaggio, quindi chiudere il file. Sembra una buona pratica se non ci sono molti messaggi in arrivo, ma se c'è un rapido flusso di conversazione questo sembra lento e richiede molto di azioni non necessarie perché il file verrà riaperto immediatamente.

Poi ho pensato a cosa succede se ho appena lasciato il file aperto e ho appena scritto i messaggi mentre arrivavano al file, quindi chiuso periodicamente. È una buona pratica? Lasciando un file aperto per lunghi periodi di tempo? Ad esempio, dopo un'ora o dopo che è stata scritta una certa quantità di dati?

Ora, penso che dovrei prendere i messaggi, archiviarli in una "cache" (come un array di stringhe), quindi salvare l'array di stringhe in un file quando la "cache" è piena. Questa è una pratica migliore?

Così ho due domande:

1) E 'buona norma lasciare un file aperto per un lungo periodo di tempo (pochi minuti ad alcune ore) se non si utilizza il file?

2) Che cosa è una buona pratica per una "cache" come sto parlando? Un array di stringhe è buono? C'è qualcosa di meglio che dovrei usare? Come andresti a conservare queste informazioni?

risposta

3

A mio parere, la procedura migliore per i registri (e simili) nelle applicazioni server è quella di decidere un ritardo accettabile e attenersi ad esso. Ad esempio, se si imposta un ritardo di 5 secondi, scrivere il codice in modo che:

  • Se si scrive qualcosa nel registro, verrà scritto "veramente" entro 5 secondi.
  • Se qualcos'altro viene scritto prima di 5 secondi, viene semplicemente aggiunto al buffer (da scrivere quando il tempo è scaduto).

In questo modo, si esegue al massimo una scrittura su disco per 5 secondi, ma è sicuramente scritto. Questo regge bene il confronto agli altri approcci:

  • Se voi i dati a filo su disco ogni volta qualche cosa viene scritto, ma aumenta il carico e ci sono, diciamo, 10.000 eventi al secondo, poi ti verrà sprecare tempo di I/O con 10.000 scritture su disco al secondo.
  • Se si lascia a Java/il sistema operativo per decidere quando svuotare i dati, ma il carico è molto basso (ad esempio nel cuore della notte), il registro potrebbe anche essere ore non aggiornate. (Se c'è un evento, non abbastanza grande da riempire il buffer, niente per ore.)

Non ho visto le API di recente per vedere se esiste un modo integrato per fare questa strategia ma è facile da codificare. A proposito, non è necessario memorizzare manualmente l'output; puoi semplicemente usare BufferedOutputStream e chiamare l'oggetto flush() ogni volta che vuoi scriverlo su disco. (In questo modo verrà scritto automaticamente anche quando si raggiunge il limite del buffer, ma probabilmente è OK se si seleziona il limite in modo ragionevole.)

Per quanto riguarda l'apertura di un file, è possibile lasciare i file aperti per tutto il tempo desiderato (solo chiudilo quando non hai più intenzione di scriverlo). Supponendo che non ci siano migliaia di file aperti e che non è necessario che più applicazioni scrivano sullo stesso file, ciò non causa alcun problema.

+0

> la procedura migliore per i registri (e simili) nelle applicazioni server è decidere un ritardo accettabile e attenersi ad essa. Potresti approfondire come farlo? Oppure indicarmi la direzione per capire come farlo? Inoltre, alcune ulteriori informazioni su come usare BuffereOutputStream sarebbe bello. Sto cercando di usarlo nel modo giusto. Ci sono altre classi che dovrebbero essere coinvolte? Come apprendere l'utilizzo del metodo flush(). Anche questa è stata un'ottima risposta grazie. – Bnannerz

+1

BufferedOutputStream è piuttosto semplice; come se fosse stato chiamato un FileOutputStream, basta fare un nuovo BufferedOutputStream (out) e usarlo come se fosse il FileOutputStream. C'è un BufferedWriter, se usi gli scrittori. Il secondo parametro è quanto grande è il buffer; l'impostazione predefinita è piuttosto piccola ma, per quanto ne so, potresti renderla 8KB o 64KB o qualsiasi altra cosa tu voglia. – sam

+1

Informazioni su come eseguire la sincronizzazione: è abbastanza semplice ma implica la concorrenza, quindi è necessario utilizzare la parola chiave sincronizzata in alcuni punti! Fondamentalmente, avere la funzione 'scrivi su file' in modo che scriva sul flusso di output bufferizzato. Controlla se hai già un timer "scarico" in sospeso. Se ce n'è uno, non fare nulla; in caso contrario, avvia una nuova discussione che dorme solo per 5 secondi (o qualsiasi altra cosa), quindi chiama a livello del flusso. (Calling flush() cancellerà il buffer e lo scriverà effettivamente sul disco.) – sam

1

1) È buona norma lasciare un file aperto per un periodo di tempo prolungato (da alcuni minuti ad alcune ore) se non si utilizza il file?

Penso che questo dipenda dal numero di messaggi che arrivano al tuo programma e dalle dimensioni di ciascun messaggio. Se la tua memoria può soddisfare il tuo calcolo, puoi pensarci. Ma penserò a un incontro per scrivere su un database quando ogni messaggio arriverà (potrebbe essere un blob). Pensa anche a cosa è successo se il tuo programma si blocca mentre scrivi sul file. Potresti perdere interi messaggi archiviati in memoria.

2) Che cosa è una buona pratica per una "cache" come sto parlando? Un array di stringhe è buono? C'è qualcosa di meglio che dovrei usare? Come andresti a conservare queste informazioni?

Se si memorizzano temporaneamente i dati nell'array di memoria è ok quando si conosce la dimensione. Altrimenti potresti usare ArrayList.

3

È assolutamente corretto lasciare un file aperto per un lungo periodo. È certamente molto meglio che aprirlo e chiuderlo più volte. La quantità di risorse utilizzate da un singolo file aperto è trascurabile; la tua unica preoccupazione sarebbe se tu avessi un sacco di file aperti (centinaia o migliaia). Ti suggerisco di aprire il file all'avvio del programma e chiuderlo al termine.

Se si utilizzano gli strumenti adatti per esaminare i file aperti contenuti nel programma o altri programmi sul sistema, si scoprirà che tutti contengono un numero di file (pochi a dozzine) aperti per tutta la loro durata - tutti i file che contengono il codice del programma (eseguibili, librerie condivise e file JAR per i programmi Java), in quanto vengono aperti e quindi mappati in memoria e spesso anche i file di registro. Questo è normale e sicuro.

Ora, è necessario lo flush lo stream (o writer, o RandomAccessFile o qualsiasi altra cosa si usi) durante questo periodo.Dovresti farlo ogni volta che devi assicurarti che tutti i dati scritti fino a quel momento siano stati scritti sul disco in modo sicuro; che potrebbe essere dopo ogni messaggio, o dopo un dato numero di messaggi, quantità di dati o periodo di tempo, come meglio credi.

Problemi correlati