Problema numeri negativi con esercizio metodi synchronized

di il
2 risposte

Problema numeri negativi con esercizio metodi synchronized

Salve a tutti ! volevo sapere se potreste cortesemente valutare a grandi linee la mia soluzione a questo esercizio che dovrebbe avere qualche problema, come vedrete più avanti.
Questo è il testo :

"Un thread Producer genera ripetutamente in modo casuale tre tipi di messaggi A, B e C, ad ogni messaggio
è associato un numero intero generato in modo progressivo dal thread Producer ed un numero intero che
verrà inserito dal thread consumer. Sono presenti tre thread ConsumeA, ConsumeB e ConsumeC che
consumano rispettivamente messaggi di tipo A, B e C e ognuno dei quali attende che arrivi il tipo di
messaggio indicato.
Il thread Producer quando invia il messaggio attende che il messaggio sia stato elaborato dal thread
consumatore e quindi stampa: il tipo di messaggio, il valore progressivo associato al messaggio ed il valore
prodotto dal consumatore.
Ogni thread ConsumerA/B/C attende che arrivi un messaggio del tipo indicato e quindi inserisce nel
messaggio la risposta che è legata al valore v fornito dal produttore che è:
-----v*10 se messaggio di tipo A
-----v*100 se messaggio di tipo B
-----v*1000 se messaggio di tipo C
e sblocca il thread produttore che è in attesa della risposta e quindi si mette in attesa di un altro
messaggio.
Realizzare quanto indicato in Java usando i metodi sincronizzati."


Ha qualche problema, mi stampa numeri negativi dopo qualche iterazione :


"sono nel messaggioB e il valore di v è 22140101
il valore di v ritorna al produttore e vale -2080957196
il valore di m è 0 e spedisce il messaggio
invio del messaggioA "

Di seguito ho inserito il codice :
public class Risorse {
	private int m; 
	private int v;
	private boolean disponibileA,disponibileB, disponibileC;
	
	public Risorse(){
	
		m = 0;
		v = 0;
		disponibileA = false;
		disponibileB = false;
		disponibileC = false;
	}

	public synchronized void treTipidiMessaggi(){
		while(true){
		
		m = (int)(Math.random()*2);
		System.out.println("il valore di m è  "+m+ " e spedisce il messaggio");
		v++;
		if(m == 0){
			disponibileA = true;
			System.out.println("invio del messaggioA");
			try {
				wait();
			} catch (InterruptedException ie) {
			}
			
		}
		if(m == 1){
			disponibileB = true;
			System.out.println("invio del messaggioB");
			try {
				wait();
			} catch (InterruptedException ie) {
			}
			
		}
		if(m == 2){
			disponibileC = true;
			System.out.println("invio del messaggioC");
		    try {
				wait();
			} catch (InterruptedException ie) {	}
		}
	}	
}	
	
	public  synchronized void messaggioC(){
		
		if(disponibileC == true){
		System.out.println("sono nel messaggioC e il valore di v è "+v);
		v = v*1000;
		System.out.println("il valore di v ritorna al produttore e vale "+v);
		disponibileC = false;
		}
		notifyAll();
	}
	
	public synchronized void messaggioB(){
		
	
		if(disponibileB == true){
		System.out.println("sono nel messaggioB e il valore di v è "+v);
		v = v*100;
		System.out.println("il valore di v ritorna al produttore e vale "+v);
		disponibileB = false;
		}
		notifyAll();
	}
		
	
	public synchronized void messaggioA(){
		
		if(disponibileA == true){
		System.out.println("sono nel messaggioA e il valore di v è "+v);
		v = v*10;
		System.out.println("il valore di v ritorna al produttore e vale "+v);
	    disponibileA = false;
		}
	
	    notifyAll();
	}
}
public class Producer extends Thread {

	private Risorse r;
	
	public Producer(Risorse r){
		this.r = r;
	}
	
	public void run(){
		
	r.treTipidiMessaggi();
	
	}
}
public class Principale {
	
	public static void main(String args[]){
		
		int M = 5;
			
			Risorse r = new Risorse();
     			Producer p = new Producer(r);
 			p.start();
					
			for(int i = 0 ; i < M ; i ++){
			ConsumerA	cA = new ConsumerA(r);
			    cA.start();
			}
		    for(int i = 0 ; i < M ; i ++){
		    ConsumerC	cC= new ConsumerC(r);
			    cC.start();
		    }
		    for(int i = 0 ; i < M ; i ++){
		    ConsumerB	   cB = new ConsumerB(r);
				    cB.start();
		    }
		
	}
}
(gli altri 2 consumer sono identici solo che al posto di ConsumerA si chiamano ConsumerB e ConsumerC

public class ConsumerA extends Thread {

	private Risorse r;
	public ConsumerA(Risorse r){
		this.r = r;
	}
	
	public void run(){
		r.messaggioA();
	}

}
Grazie in anticipo!

2 Risposte

  • Re: Problema numeri negativi con esercizio metodi synchronized

    Quanto hai scritto purtroppo non è molto buono. Innanzitutto ci sono evidenti ripetizioni di codice e logica. Se ti si chiedesse di aumentare a 4 messaggi, dovresti replicare ulteriormente il codice.
    Inoltre l'uso di wait() non è corretto. il wait() va sempre messo dentro un piccolo ciclo che deve testare la condizione che "regge" per far sì che il thread sia e resti in wait.

    Ascolta bene: invece di fare una classe (Risorse) che fa più cose, inizia innanzitutto a fare una classe (es. RisorsaMessaggio) che gestisce 1 messaggio ma senza sapere nulla di particolare sulla logica "applicativa".
    Dovrebbe avere una operazione di es. "scriviMessaggio" che il Producer usa per rendere disponibile il messaggio. E deve bloccarsi se il Consumer non ha ancora risposto.
    Dovrebbe avere una operazione di es. "leggiMessaggio" che il ConsumerX usa per leggere il messaggio. E deve bloccarsi se non c'è appunto un messaggio disponibile.
    Dovrebbe avere una operazione di es. "rispondiMessaggio" (i nomi li scegli tu ..) che il consumerX usa per rispondere al messaggio, sbloccando quindi il Producer che è nel scriviMessaggio.

    Tutto questo detto a grandi linee e se è corretto per quanto ho capito io, ovviamente.
    Valuta meglio, insomma, questi aspetti, perché altrimenti non solo non ne esci ma non fai neanche un buon codice.
  • Re: Problema numeri negativi con esercizio metodi synchronized

    Quanto hai scritto purtroppo non è molto buono. Innanzitutto ci sono evidenti ripetizioni di codice e logica. Se ti si chiedesse di aumentare a 4 messaggi, dovresti replicare ulteriormente il codice.
    Inoltre l'uso di wait() non è corretto. il wait() va sempre messo dentro un piccolo ciclo che deve testare la condizione che "regge" per far sì che il thread sia e resti in wait.

    Ascolta bene: invece di fare una classe (Risorse) che fa più cose, inizia innanzitutto a fare una classe (es. RisorsaMessaggio) che gestisce 1 messaggio ma senza sapere nulla di particolare sulla logica "applicativa".
    Dovrebbe avere una operazione di es. "scriviMessaggio" che il Producer usa per rendere disponibile il messaggio. E deve bloccarsi se il Consumer non ha ancora risposto.
    Dovrebbe avere una operazione di es. "leggiMessaggio" che il ConsumerX usa per leggere il messaggio. E deve bloccarsi se non c'è appunto un messaggio disponibile.
    Dovrebbe avere una operazione di es. "rispondiMessaggio" (i nomi li scegli tu ..) che il consumerX usa per rispondere al messaggio, sbloccando quindi il Producer che è nel scriviMessaggio.

    Tutto questo detto a grandi linee e se è corretto per quanto ho capito io, ovviamente.
    Valuta meglio, insomma, questi aspetti, perché altrimenti non solo non ne esci ma non fai neanche un buon codice.

    Se ho capito bene dovrebbe essere qualcosa del genere?
    public class Producer extends Thread{
    
    	private risorsaMessaggio rm;
    	
    	public Producer(risorsaMessaggio rm){
    		
    	}
    	
    	public void run(){
    		rm.scriviMessaggio();	
    	}
    	
    }
    
    
    
    public class ConsumerX extends Thread{
    	
    	private risorsaMessaggio rm;
    	
    	public ConsumerX(risorsaMessaggio rm){
    		
    	}
    	
    	public void run(){
    		rm.leggiMessaggio();
    		rm.rispondiMessaggio();
    	}	
    
    }
    
    
    public class risorsaMessaggio {
    	private boolean messaggioDisponibile;
    	
    	public risorsaMessaggio(){
    		messaggioDisponibile = false;
    	}
    	
    	
    	public synchronized void scriviMessaggio(){
    		messaggioDisponibile = true;
    		if(messaggioDisponibile){
    			try{
    				wait();
    			}catch(InterruptedException ie){}
    		}
    			
    		
    	}
    
    	public synchronized void leggiMessaggio(){
    		if(!messaggioDisponibile){
    			try{
    				wait();
    			}catch(InterruptedException ie){}
    		}
    	}
    	
    	public void rispondiMessaggio(){
    		messaggioDisponibile = false;
    		notify();
    		 
    	}
    }
    
Devi accedere o registrarti per scrivere nel forum
2 risposte