Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    [Java] Checksum di un file attraverso thread concorrenti.

    Spero che questo non sia contro il regolamento ma sono effettivamente due problemi diversi.

    Devo realizzare un programma checksum <InputFileName><N> che calcoli la checksum (dimensione totale del valore dei byte contenuti nel file) del file passato in ingresso tramite N thread con cui suddividere il lavoro utilizzando meccanismi di sincrnizzazione in ambiente multithread (come semafori/mutex o metodi synchronized)

    Anche in questo caso grazie in anticipo a chiunque mi sarà di aiuto.

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [Java] Checksum di un file attraverso thread concorrenti.

    Originariamente inviato da Giandella
    Devo realizzare un programma checksum <InputFileName><N> che calcoli la checksum (dimensione totale del valore dei byte contenuti nel file) del file passato in ingresso tramite N thread con cui suddividere il lavoro utilizzando meccanismi di sincrnizzazione in ambiente multithread (come semafori/mutex o metodi synchronized)
    In termine "checksum" in generale si usa per definire una qualche forma di controllo di ridondanza per verificare la integrità dei dati. Nel tuo caso, se ho capito bene, è da intendere proprio letteralmente, cioè il controllo più classico (e semplice) ovvero la somma dei byte. Operazione che appunto si presta molto bene ad essere "suddivisa".

    Ci sono diverse soluzioni, che innanzitutto si differenziano per quanto riguarda i compiti che i vari thread devono eseguire. Vedo almeno 2 scenari:

    1) Un thread si occupa di leggere sequenzialmente il file a blocchi di N byte e ogni blocco lo passa ad un thread a sé stante che si occupa di calcolare il checksum. In questo caso 1 solo thread interagisce con il file mentre gli altri X thread si occupano solo della computazione del checksum.

    2) Tutti gli X thread "sanno" del file ed ognuno accede con accesso casuale ad una sezione del file, legge il blocco e computa il checksum. Questo richiede chiaramente l'accesso al file in modo casuale. Non necessariamente 1 thread deve occuparsi di 1 sola sezione, eventualmente può anche essere "istruito" per computare il checksum di più sezioni.

    Per la gestione degli X thread la questione è più delicata e complessa. La soluzione migliore e più elegante è l'utilizzo di un thread-pool, a partire da Java 5 è disponibile quello che si chiama "executor framework" che consente di gestire facilmente un thread-pool. Ma bisogna conoscerlo discretamente bene per poterlo usare al meglio.

    Agli X thread comunque deve essere passato qualcosa, cioè bisogna in ogni caso istruire il thread per fargli fare qualcosa. Che sia l'array di byte di cui calcolare il checksum o solo la posizione/dimensione della sezione del file da esaminare ma qualcosa va passato (e poi alla fine restituito).

    Se non si vuole/può usare l'executor framework, si possono comunque creare "a mano" gli X thread. Si dovrebbe quindi usare una coda, il thread principale inserisce nella coda le informazioni e ogni thread estrae una informazione che usa per computare il checksum.

    Ho detto un po' di cose più che altro a livello teorico ... bisogna vedere cosa puoi fare tu e se hai già fatto qualcosa o proprio nulla.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Purtroppo sono ancora a zero con questo programma, visti tutti gli esami che sto preparando

    Comunque grazie per la risposta, sono orientato ad implementare il programma secondo la seconda soluzione che hai esaminato (anche perchè so molto molto poco del thread-pool).
    Nello specifico il file viene suddiviso in N parti, tante quante il numero dei thread, ed ogni thread calcola il checksum di una parte ottenendo così N valori parziali che poi sommerò.

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Giandella
    sono orientato ad implementare il programma secondo la seconda soluzione che hai esaminato
    Benissimo, allora puoi seguire i seguenti passi:

    - definisci una tua classe che estende Thread o implementa Runnable. Al costruttore passerai un String o File relativo al file e la posizione e lunghezza del segmento da esaminare. Il compito eseguito dal run() sarà quello di aprire il file con RandomAccessFile, posizionarsi al punto voluto, leggere i byte e computare il checksum. Il risultato lo metterai in un campo privato di istanza della classe, leggibile poi successivamente dall'esterno con un apposito metodo "getter" che stabilisci tu.

    - Crei N oggetti Thread e li metti in un array (se hai solo implementato Runnable c'è un passo e un array in più perché devi tenere l'array dei tuoi Runnable e l'array dei Thread). Il thread principale deve quindi preoccuparsi di determinare la lunghezza del file, calcolare posizioni/dimensioni delle sezioni e istanziare ogni thread passando questi dati.

    - Fai partire gli N thread con start() su ognuno.

    - Attendi la fine di tutti i thread (è un semplice loop in cui fai join() su ogni thread ... attendi il primo, poi il secondo, ecc...).

    - Prendi i checksum calcolati dai thread con un metodo es. getChecksum() e li sommi.

    In linea di massima una possibilità è questa ... ovviamente non è l'unica.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    anche qui problema risolto se può interessare inserisco le soluzioni, il programma consiste di 4 classi ed un'interfaccia.

    codice:
    import java.io.*;
    import java.util.concurrent.*;
    
    /**Classe contenente il main, quindi punto di accesso del programma.
     * Lo scopo della classe è quello di realizzare il conteggio del valore dei 
     * byte contenuto in un file utilizzando metodi multithreaded.**/
    
    public class Checksum {
    		
    	public static void main(String[] args) {
    		
    		//verifica numero parametri passati.
    		
    		if(args.length!=2){
    			System.out.println("numero parametri errato;si prega di inserirne 2.");
    			System.exit(1);
    		}
    		
    		//acquisizione nome file e numero thread.
    		
    			String nomefile=args[0];			//nome del file.
    			int nthread= Integer.parseInt(args[1]);		//numero di thread.
    			int nbyte=0;
    			
    			//verifica esistenza file.
    			
    			int i;
    			FileInputStream fis = null;
    			File file=new File(nomefile);
    			
    			if (!file.exists()){
    				System.out.println("file richiesto non presente.");
    				System.exit(1);
    			}
    			
    			//verifica numero thread.
    			
    			if(nthread<1){
    			System.out.println("numero thread errato;si prega di inserirne un numero >0.");
    			System.exit(1);
    		}
    			try {
    				fis=new FileInputStream(file);		//lettura file.
    				nbyte=fis.available();			//lettura numero byte.
    			} catch (Exception e) {
    				e.printStackTrace();			//gestione possibile errore.
    			}
    			
    			IBufferSum buf=new BufferSum(nthread);
    			int ncount=nbyte/nthread;			//numero byte da contare per thread.
    			int resto=nbyte%nthread;
    			byte[] buffer;
    			
    			//Creazione array di semafori per gestire il sincronismo tra padre e thread figli.
    			
    			Semaphore semafori[]=new Semaphore[nthread];
    			for(i=0;i<nthread;i++){
    				semafori[i]= new Semaphore(0);
    			}
    			
    			/**Ciclo for per associare l'analisi del file ai vari thread dividendo in parti
    			 * uguali il lavoro ad ognuno.**/
    			
    			for(i=0;i<nthread;i++){
    				if(i<nthread-1){
    					buffer=new byte[ncount];
    					try {
    						fis.read(buffer,0,ncount);
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    					SumProducer sumprod=new SumProducer(buf,buffer,semafori[i]);
    					sumprod.start();
    				}else{
    					buffer=new byte[ncount+resto];
    					try {
    						fis.read(buffer,0,ncount+resto);
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    					SumProducer sumprod=new SumProducer(buf,buffer,semafori[i]);
    					sumprod.start();
    				}
    			}
    			
    			/**Ciclo for con cui il main controlla lo stato dei semafori in attesa che 
    			siano tuti "verdi" in modo da avere il via libera per effettuare la somma totale.**/
    			
    			for(i=0;i<nthread;i++){
    				try {
    					semafori[i].acquire();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			
    			/**Creazione di un oggetto SumConsumer per la somma e la stampa del risultato.**/
    			
    			SumConsumer sumtot=new SumConsumer(buf);
    			sumtot.start();
    		}	
    	}
    codice:
    import java.util.concurrent.Semaphore;
    
    /**Interfaccia che raccoglie i metodi della classe BufferSum.**/
    
    public interface IBufferSum {
    	void insertsum(int somma,Semaphore s) throws IndexOutOfBoundsException;
    	int keepsum(int k) throws IndexOutOfBoundsException;
    	int size();
    }
    codice:
    import java.util.concurrent.Semaphore;
    
    /**Classe che implementa l'interfaccia IBufferSum e i rispettivi metodi.
     * Ha tre campi privati;un array per contenere le somme parziali del alore dei byte,
     * un intero i e un intero per la dimensione dell'array.**/
    
    public class BufferSum implements IBufferSum{
    	private int[] buffer;
    	private int i;
    	private int size;
    	
    	/**Costruttore della classe che ri+ceve un intero come parametro passato
    	 * e va a settare gli altri campi.*/
    	
    		public BufferSum(int size){ 
    			this.size=size;
    			buffer=new int[size];
    			i=0;
    		}
    
    		/**Metodo di inserimento dei valori nell'array. E' synchronized per permetere
    		 * l'inserimento da parte dei thread del valore calcolato in una cella dell'array
    		 * evitando la scrittura da parte di due o più thread in concomitanza su di una
    		 * singola cella.**/
    		
    		public synchronized void insertsum(int somma, Semaphore s) throws IndexOutOfBoundsException{
    			buffer[i] = somma;
    			i++;
    			s.release(); 	 //setta il semaforo a "verde".
    		}
    		
    		/**Metodo per prelevare il valore da una cella dell'array.**/
    		
    		public int keepsum(int k) throws IndexOutOfBoundsException{
    			return buffer[k];
    		}
    		
    		/**Restituisce la dimensione dell'array.**/
    		
    		public int size(){
    			return size;
    		}
    		
    }
    codice:
    /**Classe che realizza la somma degli elementi contenuti nell'array 
    che memorizza la somma parziale. Stampa a video del risultato.**/
    
    public class SumConsumer extends Thread{
    	private IBufferSum buf;
    	
    	//Costruttore della classe.
    	
    	public SumConsumer(IBufferSum buf){
    		this.buf=buf;
    	}
    	
    	//riscrittura del metodo run per calcolo somma totale.
    	
    	public void run(){
    		int somma=0;
    		for(int i=0;i<buf.size();i++){
    			somma=somma+buf.keepsum(i);
    		}
    		
    		//Stampa della somma a video.
    		
    		System.out.println("La somma è: "+somma);
    	}
    }
    codice:
    import java.util.concurrent.Semaphore;
    
    /**Classe che estende la classe Thread realizzata per effettuare il calcolo 
     * della somma del valore dei byte di parte del file passato in ingresso.
     * Costituita da tre campi privati;uno per memorizzare l'array di byte
     * da analizzare, uno per memorizzare il semoforo attibuito al thread e
     * uno relativo ad un oggetto IBuffer.**/
    
    public class SumProducer extends Thread{
    	
    	private byte[] buffer;
    	private Semaphore s;
    	private IBufferSum buf;
    	
    	//Costruttore della classe.
    	
    	public SumProducer(IBufferSum buf,byte[] buffer,Semaphore s){
    		this.buf=buf;
    		this.s=s;
    		this.buffer=buffer;
    	}
    	
    	/**Riscrittura del metodo run che realizza la funzione di somma parziale.**/
    	
    	public void run(){
    		int sum=0;
    		int ncount=buffer.length;
    		for(int i=0;i<ncount;i++){
    			sum=sum+buffer[i];
    		}
    		buf.insertsum(sum,s);
    	}
    }

  6. #6
    curiosità, ma quanto è grande sto file per aver bisogno di N thread per calcolare il numero di byte?
    IP-PBX management: http://www.easypbx.it

    Old account: 2126 messages
    Oldest account: 3559 messages

  7. #7
    Originariamente inviato da Santino83_02
    curiosità, ma quanto è grande sto file per aver bisogno di N thread per calcolare il numero di byte?
    il programma era solo a scopo "didattico" non aveva una finalità reale

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Giandella
    anche qui problema risolto
    Scusa se mi permetto di dirlo .... che tu l'abbia risolto ok. Che l'abbia risolto bene non ci metterei la mano sul fuoco ....

    Già solo le eccezioni non sono state gestite come si deve. Ad un certo punto catturi le eccezioni e fai un e.printStackTrace(); ma poi continui tranquillamente come se nulla fosse.

    Tutta quella gestione dei "semafori" complica solo la vita. Avevo anche descritto una soluzione alternativa: ogni thread si tiene una variabile di istanza con il "suo" checksum. Alla fine si attende la terminazione di tutti i thread e quindi si leggono i checksum parziali e si sommano. Nessuna concorrenza, niente lock, semafori o roba del genere.

    Poi c'è anche la questione dei buffer. Usi N thread ed è ok. Ma usi anche N buffer tali per cui l'insieme dei buffer è comunque la dimensione totale del file. Cioè se fai il checksum di un file di 100 MB, allochi comunque 100 MB in tutto!!

    Insomma .... sarebbe ampiamente migliorabile.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Originariamente inviato da Santino83_02
    curiosità, ma quanto è grande sto file per aver bisogno di N thread per calcolare il numero di byte?

    Dormendoci sopra mi sono accorto che ho fatto una domanda idiota.
    IP-PBX management: http://www.easypbx.it

    Old account: 2126 messages
    Oldest account: 3559 messages

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.