Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14
  1. #1

    Problema con Thread in Java

    Salve, ho un problema con un esercizio che proprio non riesco a risolvere. Devo garantire l'accesso ad un metodo a 3 thread per volta. Ho realizzato il metodo in modo che i thread in più vengano "bloccati" in un ciclo while. In questo modo:

    codice:
    private static int cont = 3; 
    public void prova_a_entrare(int id) { 
         while(cont==0) {     }
         cont--;
         System.out.println("Il thread "+id+" è entrato");
         Thread.sleep(5000);
         System.out.println("Il thread "+id+" sta uscendo");
         cont++;
    }
    Con questa realizzazione però il thread in più che viene "bloccato" nel ciclo spreca cpu inutilmente anche se non fa niente. Volevo trovare un modo per mettere in pausa il thread senza che spreca tempo di cpu.
    Avevo inizialmente pensato ad un monitor con la parola chiave synchronized, ma il monitor fa entrare solo un thread alla volta, non riesco a trovare un modo per farne entrare 3 per volta.

    Grazie a chi mi aiuta

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Classe java.util.concurrent.Semaphore, disponibile solo da Java 5.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    La traccia dell'esercitazione è la seguente:

    Un gruppo di 20 bevitori ha a disposizione una botte di vino con 3 rubinetti, contenente 100 litri di vino. Di conseguenza possono bere solo tre persone alla volta, sempre che la botte contenga ancora vino. Si suppone per semplicità che ogni bevuta faccia diminuire il vino nella botte di 1 litro.
    Si simuli la suddetta situazione in Java, utilizzando un Monitor (costrutto synchronized di java).
    Suggerimento: Il thread bevitore, dopo aver atteso un tempo casuale, deciderà di bere e si metterà in attesa se il numero di rubinetti liberi è 0; quindi controllerà la variabile contenente il vino. Qualora non ci sia più vino il thread terminerà la sua esecuzione).

    Qualcuno che mi possa aiutare?

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da pier_IP
    utilizzando un Monitor (costrutto synchronized di java).
    Se non vuoi/puoi (per qualunque motivo) usare la sincronizzazione ad "alto livello" (come ad esempio Semaphore) allora devi usare la "intrinsic condition queue" degli oggetti .... ovvero usare wait()/notify()/notifyAll() ... insieme al synchronized ovviamente.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Originariamente inviato da andbin
    Se non vuoi/puoi (per qualunque motivo) usare la sincronizzazione ad "alto livello" (come ad esempio Semaphore) allora devi usare la "intrinsic condition queue" degli oggetti .... ovvero usare wait()/notify()/notifyAll() ... insieme al synchronized ovviamente.
    E infatti l'avevo già provato con i monitor ma se dichiaro il metodo con synchronized comunque fa entrare un solo thread alla volta, invece ne dovrebbero entrare 3. Ho provato anche a usare synchronized solo per un blocco di codice all'interno del metodo, ma comunque non riesco ad avere nemmeno "l'impressione" che i thread siano entrati in 3. Mi date qualche dritta?

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da pier_IP
    Mi date qualche dritta?
    wait()/notify()/notifyAll()
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,326
    Come ti ha già detto andbin, devi usare wait(), notify()/notifyAll().

    Tu hai un ciclo while() vuoto, che si ripete sempre finchè la condizione è vera... è lì che devi bloccare il thread. Ma bloccarlo non significa fargli eseguire all'infinito il ciclo vuoto. Significa "arrestarlo", e per arrestarlo si usa il wait().

    Quando un thread esce dalla coda, dovrà chiamare notifyAll() per "risvegliare" tutti i thread bloccati, che rieseguiranno il test. Ovviamente ne entrerà solo uno.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  8. #8
    Ovviamente ne entrerà solo uno.
    Come già ho detto più volte devono entrare 3 thread per volta. Nella traccia dell'esecizio la botte ha 3 rubinetti e i "bevitori" sono 20 di conseguenza possono bere solo tre persone alla volta. Pur non avendo ancora studiato i semafori in java suppongo che dovrebbe esserci una variabile semaforo che permette a n thread di accedere alla sezione critica e così sarebbe tutto più semplice. Se l'esercizio non imponeva la realizzazione con monitor l'avrei sicuramente risolto con i semafori(documentandomi per bene) e vi avrei lasciato in pace. Se qualcuno vuole ed è in grado di aiutarmi gliene sarò grato (altrimenti non credo che frequenterò più questo forum)

  9. #9
    Utente di HTML.it L'avatar di neroux
    Registrato dal
    Aug 2009
    Messaggi
    1,973

    Re: Problema con Thread in Java

    Originariamente inviato da pier_IP
    Con questa realizzazione però il thread in più che viene "bloccato" nel ciclo spreca cpu inutilmente anche se non fa niente. Volevo trovare un modo per mettere in pausa il thread senza che spreca tempo di cpu.
    In questo caso Thread.yield()

    www.sitemeer.com » Quando un sito pare irraggiungibile

    Se ti piace ci puoi trovare anche su Facebook

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da pier_IP
    Se qualcuno vuole ed è in grado di aiutarmi gliene sarò grato
    Visto che è un "esercizio", il codice dovresti scriverlo tu ... io dovrei solo limitarmi a spiegartelo "a parole".

    Hai un metodo che deve poter essere invocato al massimo da 3 thread contemporaneamente. Ulteriori thread che volessero eseguire il codice "effettivo" che fa il lavoro del metodo, devono mettersi in attesa finché non si libera un "permesso".

    La prima cosa che serve è ovviamente una variabile che fa da "contatore". Non deve essere di certo "locale" nel metodo .... deve essere di durata maggiore. Se il metodo è di istanza, anche la variabile dovrebbe essere di istanza. Se fosse di classe, altrettanto dovrebbe esserlo la variabile.

    Servono anche wait() e notifyAll(), come è già stato detto in precedenza nella discussione. Questi metodi di Object sono particolari, vanno invocati solo ed esclusivamente su un oggetto di cui il thread corrente ne possiede il "lock".
    Serve quindi comunque la parola chiave 'synchronized' per poter acquisire il lock di un oggetto.
    Quale oggetto è facile da stabilire: se il metodo è di istanza, l'oggetto su cui è stato invocato il metodo (il 'this') mentre se fosse di classe, l'oggetto Class della classe.

    La cosa importante da capire è che il synchronized non va messo sul metodo (nella dichiarazione del metodo). Se così fosse, ci sarebbe comunque una "serializzazione" degli accessi che non è certo quello che si vuole. Qualunque numero di thread deve poter entrare subito immediatamente nel metodo e internamente va fatta la gestione dei "permessi" (max 3 appunto).

    Il metodo dovrebbe essere visto come composto logicamente di 3 fasi:

    1) C'è un permesso disponibile? Se sì, acquiscilo (e vai avanti). Altrimenti mettiti in attesa.
    2) Esecuzione del "lavoro" principale del metodo.
    3) Rilascio del permesso.

    La prima fase è quella più delicata. Il thread deve essere sospeso con wait() se non c'è un permesso disponibile. Ne conseguono 2 cose: ci vuole un test (sul contatore) e bisogna acquisire un lock.
    Se il permesso invece c'è (subito o dopo un po' di attesa) si deve proseguire ma prima si deve indicare l'acquisizione del permesso e questo vuol dire che devi modificare il valore della variabile (scegli tu se a decremento da 3 o a incremento da 0).
    Ma tutto questo va comunque fatto tenendo il lock. La variabile infatti è "condivisa" e non deve essere acceduta senza sincronizzazione. E anche per il wait.

    Poi viene eseguito il lavoro. Qui, in questa fase, il thread non deve possedere alcun lock (altrimenti ci sarebbe la serializzazione).

    Il rilascio è più semplice. La variabile va di nuovo aggiornata per indicare un permesso in più. E va fatta la notifica per "svegliare" gli altri thread. Entrambe le cose vanno fatte acquisendo e tenendo, ancora una volta, il lock. Per la variabile perché è condivisa e per la notifica per quanto detto prima sui metodi wait/notifyAll/notify.

    Ti è più chiaro ora?


    Originariamente inviato da pier_IP
    altrimenti non credo che frequenterò più questo forum
    Beh, mi spiace se il forum ti avesse dato per caso una impressione negativa ..... vedi tu.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

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.