Newsgroup: it.comp.java
Titolo: Lettura conconrrenziale files

ho implementato la lettura concorrenziale di una serie di file da parte di
un applicazione server.
il metodo che ho utilizzato però non è il massimo dell'efficienza; è
stutturato così:
classe datiFile:
   inputstream
   numero di canali aperti sul fiel
hashmap<nomeFile, datiFile>
quando viene effettuata una richiesta,
- se il nome del file non è presente nella hashmap, viene aperto ed i suoi
dati aggiunti nella hashmap.
- se il nome è presente, vengono usati i dati già presenti.
- in entrambi i casi, viene incrementato il contatore dei canali.
quando viene conclusa una lettura, il contatore viene decrementato, e se
il contatore è uguale a zero, il file viene chiuso.
esiste un modo più semplice, ad esempio una verifica diretta se esistono
già altri canali aperti su un file?
ciao!
saverio m.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 - in entrambi i casi, viene incrementato il contatore dei canali.
Cioè, fammi capire: in pratica tu hai degli inputstream che vengono
letti in concorrenza da un numero di thread pari al numero di canali,
giusto?
Se è così, non funziona mica. La lettura concorrenziale sullo stream
non si può fare, ma se anche lo sincronizzi farebbe lo stesso del gran
casino.


Dunque, posto che è sbagliatissimo l'approccio usato prima (rimuoviamo,
rimuoviamo...), la lettura concorrenziale su più canali di un unico
inputstream funziona, invece.
Allego il listato di un programma che ho scritto che crea un file
composto da lettere dell'alfabeto; successivamente viene aperto uno
stream e partono più thread che creano un canale, leggono in concorrenza
una parte differente dello stream e scrivono in sicronia ogni carattere
letto insieme ad un altro carattere che permette di riconoscere il
thread su un altro file (che serve per verificare la correttezza della
lettura).
in pratica, supponendo quattro thread
file input:
AAAA...BBBB...CCCC...DDD
markers dei thread:
a, b, c, d
file di output, se tutto corretto:
AaBbCcDdBbDdAaDd...
Forse esistono delle condizioni particolari in cui questo modo di
leggere non funziona?
Ciao!
Saverio M.
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
public class ConcurrentNioRead {
	protected static final String INPUT_FILENAME = "testFile.txt";
	private static final byte NUM_THREADS = 4;
	private static final int CHUNK_SIZE = 10*1024;
 
	private FileInputStream inpStream;
	private NioRead[] nioRead; // threads array
 
	private static final String OUTPUT_FILENAME = "outputFile.txt";
	private PrintWriter outWriter;
 
	public static void main(String[] args) throws Exception {
		@SuppressWarnings("unused")
		ConcurrentNioRead nio = new ConcurrentNioRead();
	}
 
	public ConcurrentNioRead() throws Exception {
		createInputFile();
		setupStreams();
		createThreads();
		readAndWrite();
		end();
	}
 
	/***************************************************************************
	 * Creates a file composed by N chunks; every chunk is filled with only one
	 * character corresponding to its index. Eg. 11111222223333344444
 
**************************************************************************/
	private void createInputFile() throws Exception {
		PrintWriter testWriter = new PrintWriter(new FileWriter(INPUT_FILENAME));
		for (byte chunkIdx=0; chunkIdx<NUM_THREADS; chunkIdx++) {
			for (int chunkPos=0; chunkPos<CHUNK_SIZE; chunkPos++) {
				testWriter.print((char)(chunkIdx + 97)); // converts to uppercase letter
			}
		}
 
		testWriter.close();
	}
 
	private void setupStreams() throws Exception {
		inpStream = new FileInputStream(INPUT_FILENAME);
		outWriter = new PrintWriter(OUTPUT_FILENAME);
	}
 
	private void createThreads() throws Exception {
		nioRead = new NioRead[NUM_THREADS];
 
		for (byte idx=0; idx<NUM_THREADS; idx++) {
			nioRead[idx] = new NioRead(idx);
		}
	}
 
	private void readAndWrite() {
		for (byte idx=0; idx<NUM_THREADS; idx++) {
			nioRead[idx].start();
		}
		for (byte idx=0; idx<NUM_THREADS; idx++) {
			try {nioRead[idx].join();} catch (Exception e) {}
		}
	}
 
	private void end() throws Exception {
		inpStream.close();
		outWriter.close();
		System.out.println("Finished.");
		System.out.println("Please analyse file " + 
System.getProperty("user.dir") + "\\" + OUTPUT_FILENAME);
		System.out.println("To each uppercase letter the same lowercase letter 
should follow.");
	}
	protected synchronized void printThreadChar(byte threadIdx, byte 
readChar) {
		outWriter.print((char)threadIdx);
		outWriter.print((char)readChar);
	}
	class NioRead extends Thread {
		private byte threadChar;
		private FileChannel fChan;
		private MappedByteBuffer buffer;
 
		public NioRead(byte threadIdx) throws Exception {
			threadChar = (byte)(65 + threadIdx); // converts to lowercase letter
			fChan = inpStream.getChannel();
			int pos = threadIdx * CHUNK_SIZE;
			buffer = fChan.map(FileChannel.MapMode.READ_ONLY, pos, CHUNK_SIZE);
		}
 
		public void run() {
			for (int cnt=0; cnt<CHUNK_SIZE; cnt++) {
				printThreadChar(threadChar, buffer.get());
			}
			try {fChan.close();} catch (Exception e) {}
		}
	}
}

Beh, se rimane solo lettura certo che funziona. Insomma, non ci vuole un 
esperto di sistemi operativi per sapere come funzionano open() e dup(): ogni 
file e' possibile associare piu' di un file descriptor... :)
Magari se inizi pure a scriverci e' MOLTO probabile che ottieni un gran 
casino, sincronizzato o meno (a meno di non sincronizzare tutta la procedura 
di accesso/modifica, ma a quel punto che te ne fai dei thread ?)
ciao
"Saver J. Simpson" <1@2.3> ha scritto nel messaggio 
news:44350...@x-privat.org...
