Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453

    [JAVA] thread problema notify() e notifyAll() in esercizio

    ciao a tutti... sto dando un esame di java, e ho un problema con questo programma:

    vi posto il testo: il file Pesa.java è dato.

    Definire in Java quanto richiesto (scrivere nel file Esa.java, tradurre, collegare ed eseguire utilizzando i
    comandi indicati nelle avvertenze).
    Il file contiene una classe MioThread che estende Thread. Ogni MioThread possiede un numero
    proprio num e memorizza il numero proprio di un altro MioThread. Inoltre, ogni MioThread possiede
    un array di riferimenti ad altri MioThread. L'elemento i-esimo dell'array contiene un riferimento al
    MioThread di numero proprio i. La classe prevede il costruttore MioThread(int num, int succ) e un
    metodo setArray(MioThread[] ar). Un MioThread può trovarsi nello stato attivo o disattivo. Il
    MioThread che ha num pari a 0 parte nello stato attivo, mentre tutti gli altri partono nello stato
    disattivo. Nello stato disattivo, i MioThread si sospendono in attesa si diventare attivi. Un MioThread
    attivo stampa la stringa “MioThread num”, attiva il MioThread numero succ (a meno che succ non
    valga -1), quindi termina.
    Il file contiene, inoltre, la classe Esa, con un metodo fai(int[] arsucc), che crea un MioThread per ogni
    elemento dell'array arsucc, con num un numero progressivo a partire da 0 e succ pari al valore
    corrispondente nell'array arsucc. Successivamente, il metodo chiama opportunamente setArray su ogni
    MioThread creato e, infine, li avvia tutti.
    codice:
    // file Esa.java
    class MioThread extends Thread
    {	private int num;
    	private int succ;
    	private MioThread[] ref;
    	private boolean stato;	//true: attivo	false: disattivo
    	public MioThread(int num, int succ)
    	{
    		this.num = num;
    		this.succ = succ;
    		this.stato = (num == 0);
    	}
    		
    	public void setArray(MioThread[] ar)
    	{
    		ref = ar;
    	}
    	
    	public synchronized void attiva()
    	{
    		stato = true;
    		notify();	// CON QUESTO FUNZIONA
    	}
    	
    	public synchronized void run()
    	{
    		try{	
    			while(!stato)
    				 wait();
    
    		Console.scriviStringa("MioThread "+num);		
    		}catch(InterruptedException e){	}
    		
    		if(succ!=-1)
    		{	ref[succ].attiva();
    			//notifyAll();	// CON QUESTO NON FUNZIONA
    		}
    	}
    }
    
    class Esa
    {	public void fai(int[] arsucc)
    	{	
    		MioThread[] arr = new MioThread[arsucc.length];
    
    		for(int i = 0; i<arsucc.length; i++)
    			arr[i] = new MioThread(i, arsucc[i]);
    			
    			
    		
    		for(int i = 0; i<arsucc.length; i++)
    			arr[i].setArray(arr);
    		for(int i = 0; i<arsucc.length; i++)		
    			arr[i].start();
    	}
    
    }
    codice:
    //file Pesa.java
    class Pesa {
    	public static void main(String[] args) {
    		int[] arsucc = { 2, 3, 1, -1 };
    		Esa esa = new Esa();
    		esa.fai(arsucc);
    	}
    }
    L'output dovrebbe essere
    codice:
    MioThread 0
    MioThread 2
    MioThread 1
    MioThread 3
    Come ho scritto nei commenti, se metto quella notify() nella funzione attiva() funziona (come fa nella soluzione dell'esercizio), mentre se metto, come mi tornerebbe logico, la notifyAll() nel metodo run() ottengo la stampa MioThread 0 e non prosegue.

    Non capisco come mai: io ho dei thread bloccati sul wait() nel ciclo che testa il booleano stato. Il thread "MioThread 0" parte (perchè è l'unico con "stato" = true), setta a true "stato" del thread ref[succ]: a questo punto, se facessì notify(), penso, sbloccherei uno a caso fra i thread() bloccati, ma non è detto che sveglierei proprio quello a cui ho settato stato a true, che è l'unico in grado di continuare, quindi ho pensato che fosse giusto mettere notifyAll(). Si svegliano tutti, chi si ritrova stato = true puo' procedere, gli altri tornano sul wait().

    Eppure non è così. Potreste spiegarmi come mai la mia soluzione (notifyAll() nel run()) non va bene, e invece quel notify() nella attiva() si?

    Grazie a tutti

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

    Re: [JAVA] thread problema notify() e notifyAll() in esercizio

    Originariamente inviato da Kilin
    Potreste spiegarmi come mai la mia soluzione (notifyAll() nel run()) non va bene, e invece quel notify() nella attiva() si?
    Sì, lo spiego subito. Intanto sai già che notifyAll() "risveglia" più thread mentre notify() solo 1 al massimo.

    La questione è che i due notify sono metodi istanza e risvegliano solo quei thread che sono in wait su quel oggetto!! La documentazione di notify() infatti dice: Wakes up a single thread that is waiting on this object's monitor. Mentre per notifyAll() dice: Wakes up all threads that are waiting on this object's monitor.

    Nota il "on this object's monitor" per entrambi.

    Quindi nel tuo codice succede questo. Se invochi il notifyAll() nel run(), non funziona. Perchè stai cercando di risvegliare .... solo sè stesso, che tra l'altro non è più in wait (=niente effetto)!

    Mentre il notify() nel attiva() funziona, perché tu da un altro thread (quello precedente come sequenza) invochi l'attiva sul successivo thread e il notify risveglia quello! (non quello nel cui contesto hai invocato l'attiva ma il thread sul cui oggetto hai invocato l'attiva!)
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    ti ringrazio per la risposta.. okei, ora l'esercizio mi è chiaro.. ho le idee un po' confuse su questa parte...

    a questo punto mi sfugge un po' il meccanismo al di fuori di questo caso particolare, cioè: quand'è che più thread si bloccano su una stessa wait-list, e dove va fatta la notify() per farli uscire? mi faresti un esempio?

    grazie comunque!

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Kilin
    a questo punto mi sfugge un po' il meccanismo al di fuori di questo caso particolare, cioè: quand'è che più thread si bloccano su una stessa wait-list, e dove va fatta la notify() per farli uscire? mi faresti un esempio?
    L'esempio a parole è semplice: immagina una Queue (coda) con capacità limitata che ha metodi put() e get() di tipo "bloccante" (put blocca se non c'è spazio, get blocca se non ci sono elementi).

    Immagina un unico oggetto Q, istanza della coda e immagina 3 thread A B e C. I primi due A e B cercano di fare dei put() ma la coda è piena. Cosa succede? All'interno della put c'è una wait (sull'oggetto stesso) e i due thread si mettono pertanto in wait entrambi su quel oggetto Q. Quando il thread C fa una get(), estrae e quindi libera spazio e fa un notify(). Tra i due thread A e B solo uno viene risvegliato e ha quindi possibilità di completare l'inserimento.
    Nel caso di una coda ha più senso un notify() piuttosto che un notifyAll(), perché il get estrae solo 1 elemento .... non avrebbe senso risvegliare più thread.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    okei, ti ringrazio! ho capito dov'era il baco nel mio ragionamento...

    mi era sfuggito il discorso che ogni oggetto ha un wait-set. Una wait() fatta su un oggetto blocca un thread nel wait-set di tale oggetto. Condividendo gli oggetti tra più thread in pratica si condividono i wait-set!

    Una cosa, dimmi se dico cavolate: se ogni thread si facesse le wait() nel proprio metodo run() (e non ad esempio non attraverso metodi di altre classi richiamate nel run()), non capiterebbe mai di avere più thread in attesa nello stesso wait-set, dato che ogni thread finirebbe nel wait-set relativo all'istanza dell'oggetto classe che possiede il run(), l'esecuzione del quale è il thread stesso (che frasi contorte...)

    cioè, in poche parole: ogni thread sarà relativo all'istanza di uno specifico oggetto di una classe che deriva da Thread; se ognuno fa la wait() all'interno del proprio metodo run(), chiama di fatto la wait() sulla specifica istanza che lo ha generato, e dunque se tutti fanno così ciascuno finisce, da solo, in un wait-set diverso.

    Right?

    grazie ancora!

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Kilin
    cioè, in poche parole: ogni thread sarà relativo all'istanza di uno specifico oggetto di una classe che deriva da Thread; se ognuno fa la wait() all'interno del proprio metodo run(), chiama di fatto la wait() sulla specifica istanza che lo ha generato, e dunque se tutti fanno così ciascuno finisce, da solo, in un wait-set diverso.
    Esatto. Il notifyAll() che pensavi di mettere nel run() di MioThread non funziona proprio per questo motivo. Se ogni thread fa la wait() sulla sua istanza di MioThread, una notify() sempre sul proprio MioThread non ha alcuna influenza sugli altri thread.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    ti ringrazio molto di avermi chiarito le idee, ora ho afferrato il meccanismo

    grazie ancora, alla prossima!

  8. #8
    Utente di HTML.it L'avatar di Kilin
    Registrato dal
    Mar 2003
    Messaggi
    453
    (tra parentesi, ottimo lavoro il link agli esempi in java che hai in firma... quando ho un po' di tempo mi sa che avrò di che studiare :-))

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.