Concorrenza, fare wait() per ogni oggetto

di il
13 risposte

Concorrenza, fare wait() per ogni oggetto

Salve,
Devo svolgere questa traccia per un compito, ma non ho idea di come farla.

Ho una lista di oggetti di lunghezza n e devo creare una funzione che per ogni oggetto della lista mi crea un thread con lo scopo di fare la wait su quell'oggetto. Ovviamente poi devo fare anche la funzione che mi sveglia tutti gli oggetti, ma quella è più semplice.

Quindi cosa ho pensato: faccio un ciclo for( Object i : lista) cosi prendo l'object i della lista, poi creo un nuovo thread all'interno del ciclo che fa i.wait(). Solo che non procede con tutti gli altri oggetti della lista la mia funzione.

Come potrei fare?

13 Risposte

  • Re: Concorrenza, fare wait() per ogni oggetto

    Yves ha scritto:


    Ho una lista di oggetti di lunghezza n e devo creare una funzione che per ogni oggetto della lista mi crea un thread con lo scopo di fare la wait su quell'oggetto. Ovviamente poi devo fare anche la funzione che mi sveglia tutti gli oggetti, ma quella è più semplice.

    Quindi cosa ho pensato: faccio un ciclo for( Object i : lista) cosi prendo l'object i della lista, poi creo un nuovo thread all'interno del ciclo che fa i.wait(). Solo che non procede con tutti gli altri oggetti della lista la mia funzione.
    Per iniziare, è necessario chiarire alcune cose: innanzitutto per poter invocare wait()/notify()/notifyAll() su un oggetto è obbligatorio acquisire prima il monitor ("lock") di quell'oggetto, ovvero, è necessario usare la parola chiave synchronized.

    Il wait() comunque di norma NON lo si fa così direttamente al volo e basta. Il wait() tipicamente si mette in un ciclo (solitamente un while() ) che deve testare la condizione che deve "reggere" affinché il thread vada e resti in sospensione.
    Faccio sempre l'esempio della coda "bloccante" (perché abbastanza chiaro/ovvio), dove se la coda è vuota, il thread che fa un estrai() deve stare in wait. Quindi nel estrai() si farà una cosa tipo:
    while (_condizione_coda_vuota_) {
        wait();
    }
    Ci sono vari motivi, storici e pratici per questo approccio con il while, che non sto ora a descrivere meglio per brevità.
    Quindi il tuo caso d'uso sicuramente non calza molto bene il modo tipico di utilizzo del wait().

    Ma il wait() diretto (cioè senza test/cicli) comunque lo puoi fare, potrebbe non essere un problema. E probabilmente nel tuo caso d'uso può anche funzionare come ti aspetti.

    Comunque, per creare un thread devi estendere Thread o implementare Runnable. In entrambi i casi, farai un costruttore che riceve l'oggetto che poi mantieni come variabile di istanza nel TuoRunnable (o TuoThread, non importa). Quindi nel run() potrai usare l'oggetto.

    Da quanto hai detto, purtroppo non è molto chiaro il problema o dubbio. Se quanto ho detto non ha chiarito, precisa meglio i tuoi dubbi e magari posta anche il codice.
  • Re: Concorrenza, fare wait() per ogni oggetto

    Sembra che a parole spiegare questa cosa sia difficile, siccome è una roba un po' astratta, quindi ti metto il mio codice cosi magari si capisce meglio.

    La funzione penso sia giusta, cosa ne pensi/pensate?
    public void waitAll() throws InterruptedException{
    		for (Object iObject : list) {
    			 new Thread(()->{
    				synchronized (iObject) {
    					
    					try {
    						System.out.println("sono thread " + Thread.currentThread().getId() + " e metto in attesa" + iObject);
    						iObject.wait();
    						System.out.println("sono thread " + Thread.currentThread().getId() + " e ho svegliato" + iObject);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    			}).start();
    		}
    	}
    	
  • Re: Concorrenza, fare wait() per ogni oggetto

    Yves ha scritto:


    La funzione penso sia giusta, cosa ne pensi/pensate?
    Hai fatte le cose molto "compattate", cioè definendo il Runnable con una lambda expression e usando direttamente iObject del foreach che quindi diventa una variabile effectively final. E poi facendo lo start "al volo" sul Thread appena creato.

    È più compatto di quello che avevo suggerito io (non potevo certo sapere se conoscevi lambda expression o no) ma comunque il codice, ad occhio, è tecnicamente corretto e fa ciò che avevi indicato nel post di inizio.
    Quindi ci sono dubbi o problemi a riguardo?
  • Re: Concorrenza, fare wait() per ogni oggetto

    Grazie della risposta, avrei un'ultimo dubbio.

    Se volessi creare una funzione che fa la notify su tutti gli oggetti della lista, dovrei fare la stessa cosa della waitAll, cioè creare 1 thread e anzichè fare wait() su quellpoggetto faccio notify?
  • Re: Concorrenza, fare wait() per ogni oggetto

    Yves ha scritto:


    Se volessi creare una funzione che fa la notify su tutti gli oggetti della lista, dovrei fare la stessa cosa della waitAll, cioè creare 1 thread e anzichè fare wait() su quellpoggetto faccio notify?
    No, basta un banale ciclo facendo per ciascun oggetto il notify() (acquisendo naturalmente il lock prima).
  • Re: Concorrenza, fare wait() per ogni oggetto

    Però prima di far partire il ciclo sarebbe meglio fare una thread.sleep(1000) per far si che il thread waker non parta prima che un'altro thread faccia la wait no?
  • Re: Concorrenza, fare wait() per ogni oggetto

    public void wakeAll() throws InterruptedException {
    		for (Object iObject : list) {
    			synchronized (iObject) {
    				Thread.sleep(1000);
    				System.out.println("sto per svegliare " + iObject);
    				iObject.notify();
    				
    			}
    			
    		}
    	}
    Un qualcosa del genere dovrebbe funzionare!
  • Re: Concorrenza, fare wait() per ogni oggetto

    Yves ha scritto:


    Però prima di far partire il ciclo sarebbe meglio fare una thread.sleep(1000) per far si che il thread waker non parta prima che un'altro thread faccia la wait no?
    Sì certo (ovviamente), ed è anche utile per vedere bene la differenza tra le due stampe, prima e dopo il wait() che hai fatto.

    Yves ha scritto:


    public void wakeAll() throws InterruptedException {
    		for (Object iObject : list) {
    			synchronized (iObject) {
    				Thread.sleep(1000);
    				System.out.println("sto per svegliare " + iObject);
    				iObject.notify();
    			}
    		}
    	}
    Tecnicamente sì ma lo sleep ha senso che sia uno solo prima di tutti i notify. Non uno sleep per ciascuna notify!
    A meno che vuoi veramente vedere che ciascuno si "sveglia" a distanza di 1 sec. Dipende da cosa vuoi "vedere" in output.
  • Re: Concorrenza, fare wait() per ogni oggetto

    Va bene, sei stato gentilissimo, non come quelli di stack overflow, ai quali ho fatto la stessa domanda e non mi hanno neanche risposto!

    Posso fare altre domande in merito alla concorrenza in java prossimamente?
  • Re: Concorrenza, fare wait() per ogni oggetto

    Yves ha scritto:


    Posso fare altre domande in merito alla concorrenza in java prossimamente?
    Certo! (e io sono tra quelli che la concorrenza in Java la conosce benissimo ...)
  • Re: Concorrenza, fare wait() per ogni oggetto

    Wow quanto ti invidio.
    Poi è un'argomento pure interessantissimo!
    Vorrei conoscerla anche io, almeno per passare l'esame ahah

    PS: hai qualche giuda da consigliarmi?
  • Re: Concorrenza, fare wait() per ogni oggetto

    Yves ha scritto:


    PS: hai qualche giuda da consigliarmi?
    Guarda ... puoi vedere i libri su cui ho studiato io nella pagina about del mio (nuovo) sito in firma.
  • Re: Concorrenza, fare wait() per ogni oggetto

    Perfetto, grazie mille!
Devi accedere o registrarti per scrivere nel forum
13 risposte