Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2012
    Messaggi
    56

    Come si ferma un thread?

    Salve
    vi spiego il mio problema, innanzitutto ecco il codice del metodo run

    codice:
    public void run() {
            while (true) {
                synchronized (this) {
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MioThread.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                faiQuesto();
            }
        }
    il thread viene risvegliato da un'altra classe che gli passa informazioni sulle cose da fare all'interno del metodo "faiQuesto()"
    adesso mi capita che quando la classe che invoca questo thread finisce mi lancia un eccezione giustamente perchè il thread è ancora attivo, ed è in wait
    come devo fare per farlo terminare correttamente?
    grazie

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320

    Re: Come si ferma un thread?

    Originariamente inviato da AspxTM
    come devo fare per farlo terminare correttamente?
    grazie
    Ci sono due cose da fare:

    1) Assicurarsi che i thread in wait vengano risvegliati, chiamando un notifyAll() quando le condizioni per la prosecuzione sono valide.

    2) Fare in modo che il thread sia collaborativo: evita i cicli volutamente infiniti ( while(true) ), sostituendoli con dei cicli monitorati (quindi, con una guardia data da una variabile booleana); aggiungi al thread un metodo che consenta di cambiare la condizione di elaborazione:

    codice:
    boolean continuaElaborazione = true;
    ...
    while( continuaElaborazione ) {
       ...
    }
    ...
    public void ferma() {
       continuaElaborazione = false;
    }
    In questo modo, quando non sarà più necessaria l'elaborazione da parte del thread, invocherai il metodo ferma() sul thread stesso ed il prossimo notifyAll() farà il suo dovere.

    PS: il thread non dovrebbe mettersi in wait() da solo, ma dovrebbe essere messo in wait() da qualcun'altro che avrà poi la facoltà di invocare un notify()/notifyAll() per risvegliare il/i thread.


    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

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2012
    Messaggi
    56
    e come posso risolvere allora questa cosa evitando che il thread si metta da solo in wait?
    cioè a me serve che il thread esegua il metodo "faiQuesto()" solo dopo che la classe che ha istanziato gli passi le informazioni, anche perchè senza di queste il metodo "faiQuesto()" mi ritorna un nullpointerexception
    Grazie

  4. #4
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Non so se ho visto giusto, ma mi sa che stai sbagliando approccio: per fare quello che vuoi tu è sufficiente fare in modo che la classe passi al thread le informazioni prima di farlo partire:

    codice:
    ...
    // Creo il thread
    MioThread mt = new MioThread();
    
    // Gli passo tutte le informazioni di cui ha bisogno
    mt.passaInformazioni( ... );
    
    // Alla fine di tutto, faccio partire il thread
    mt.start();
    Il wait()/notify() è una tecnica di "sincronizzazione"... ovvero, un thread che per lavorare ha bisogno di alcuni dati, li attende da qualcun altro (magari un altro thread) in un determinato posto e sarà questo posto che mette in wait() il thread e lo risveglia al momeno giusto con un notify()/notifyAll().


    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

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2012
    Messaggi
    56
    si ma nel mio caso il "passaInformazioni()" deve essere invocato periodicamente (ogni tot millisecondi secondo la logica della classe che lo invoca) e per non lanciare tantissimi thread ho preferito lasciarne uno che gestisca tutte le chiamate.
    per questo avevo scelto di introdurre il wait() e notifyAll()

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Originariamente inviato da AspxTM
    si ma nel mio caso il "passaInformazioni()" deve essere invocato periodicamente (ogni tot millisecondi secondo la logica della classe che lo invoca) e per non lanciare tantissimi thread ho preferito lasciarne uno che gestisca tutte le chiamate.
    per questo avevo scelto di introdurre il wait() e notifyAll()
    Anche qui non so se ho visto giusto, ma credo che il tuo problema sia riconducibile a quello del Produttore/Consumatore:
    http://www.java2s.com/Code/Java/Thre...nsumerTest.htm

    Qui c'è un approccio diverso, in cui è il singolo thread a mettersi in wait() e l'altro (che lo conosce!), lo risveglia.
    http://www.java2s.com/Code/Java/Thre...ooperation.htm

    Osserva, comunque, il primo approccio: non è il thread a mettersi in wait(), ma è l'oggetto da cui lui prende i dati a metterlo in wait() quando i dati non ci sono, ed è sempre questa classe che lo risveglia quando i dati finalmente arrivano.

    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

  7. #7
    Utente di HTML.it
    Registrato dal
    Feb 2012
    Messaggi
    56
    forse non riesco a capire la logica del producer consumer test
    però da quanto vedo nel secondo esempio del thread cooperation è il thread (waitperson) che si mette in wait e il restourant lo richiama con la notify quando vengono persone, se ho ben capito.

  8. #8
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Originariamente inviato da AspxTM
    forse non riesco a capire la logica del producer consumer test
    però da quanto vedo nel secondo esempio del thread cooperation è il thread (waitperson) che si mette in wait e il restourant lo richiama con la notify quando vengono persone, se ho ben capito.
    No, è lo Chef (il thread produttore) che lo risveglia (guarda il corpo del run). Solo che, per poterlo fare, deve conoscerlo (avere un riferimento a lui), ed infatti il ristorante glielo passa durante la costruzione.

    Questo, comunque, è un caso particolare: il primo caso è il classico:

    Ho uno o più thread Consumatori
    Ho uno o più thread Produttori
    Ho un oggetto di sincronizzazione (il "parcheggio dei dati").

    Consumatori e Produttori conoscono solo il parcheggio dei dati (hanno, ciascuno, un riferimento al parcheggio dei dati).

    Il consumatore chiede un dato al parcheggio. Se nel parcheggio c'è il dato, lo ottiene e lo lavora; il parcheggio quindi chiama notify()/notifyAll() per risvegliare un produttore eventualmente in attesa. Se non c'è il dato, è il parcheggio che chiama wait() ed il consumatore si ferma.

    Il produttore depone i dati nel parcheggio. Se nel parcheggio c'è posto, il dato viene depositato e il parcheggio chiama notify()/notifyAll() per risvegliare un consumatore eventualmente in attesa. Se non c'è posto, il parcheggio chiama wait() ed il produttore si ferma.


    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

  9. #9
    Utente di HTML.it
    Registrato dal
    Feb 2012
    Messaggi
    56
    ok ora mi è più chiaro il concetto, devo solo applicarlo al mio problema

    quale mi conviene implementare? cioè creo un'altra classe che mi fa da parcheggio oppure mi tengo l'istanza del thread e lo blocco/ risveglio dalla classe chiamante? al momento il mio codice è così strutturato

    qui il run del thread
    codice:
       public void run() {
            while (run) {
                synchronized (this) {
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MioThread.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                faiQuesto();
            }
        }
    questo è il codice della classe che lo richiama (ovviamente questo è in un blocco istruzioni che si ripete ogni tot millisecondi con x e y diverse ogni volta)
    codice:
            istanzaMioThread.tieniLeInformazioni(x, y);
            synchronized (this.istanzaMioThread) {
                this.istanzaMioThread.notify();
            }

  10. #10
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Mi pare che, ora, il tuo codice sia praticamente della stessa forma della soluzione 2, quindi dovrebbe già essere a posto così. Oltretutto, tu non ha un produttore (ovvero, il produttore è la stessa classe che istanzia il thread), quindi non hai bisogno di un "parcheggio".

    Così com'è dovrebbe già funzionare, se non ho guardato male... o ci sono ancora dei problemi?


    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

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.