|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Mar 2012
Messaggi: 33
|
[JAVA] Terminazione Thread
Salve a tutti, ho creato un programma che sfrutta i thread per effettuare una esecuzione ottimizzata di una serie di job.
La struttura del programma è composta da un thread padre che genera altri thread che a loro volta possono generare altri thread. Dopo aver creato questo bell'albero di thread mi rimane un problema, vorrei sapere quando tutti questi thread terminano e stampare a video che hanno terminato. Non credo vi sia bisogno di codice, la struttura del programma è molto semplice. PS: ho provato ad usare anche il pool di thread, ma non riesco a venirne fuori. Grazie a coloro che mi aiuteranno. |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: May 2008
Città: Seattle (WA)
Messaggi: 306
|
Quote:
__________________
"Considerate la vostra semenza fatti non foste a viver come bruti ma per seguir virtute e canoscenza" |
|
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Mar 2012
Messaggi: 33
|
Ti ringrazio per la risposta, ma purtroppo non ho la possibilità di tenere "sott'occhio" tutti i thread.
In sostanza partono autonomamente, e in maniera totalmente sporadica, perchè ogni thread può lanciarne a sua volta degli altri, quindi non ho la possibilità di sapere quanti sono o quindi memorizzarli in un array o lista. Per come è ora il mio programma avvio i thread e poi l'applicativo termina quando tutti i thread terminano, ma non vorrei che un thread fosse "appesantito" nel tener conto se i thread che ha generato sono attivi. Potrei provare a creare una classe con un metodo che ogni qualvolta viene creato un thread quest'ultimo viene inserito in un array, ma anche in quel caso non posso sapere se i thread che ho lanciato fino a quel momento sono tutti o ne manca qualcuno. Mi spiego meglio, se i thread che vengono lanciati sono 10 in totale (fra thread principale e sottothread creati dinamicamente) potrei creare man mano la lista che contiene i thread e chiamare su ognuno di essi la join, ma potrei avere che ho listato 7 thread terminati e facendo la join vedo che sono tutti effettivamente terminati, ma i restanti 3 potrebbero partire dopo. A me servirebbe un modo per far dire ad ogni thread (magari ad un metodo) "avviato" (quando viene creato e avviato) e "ho terminato" (quando termina). Forse sono un pò contorto nello spiegarmi, ma non saprei fare di meglio. Edit: ho provato a listare man mano i thread, ma ovviamente ho un errore per modifica concorrente della lista, infatti la lista viene modificata dinamicamente e il for che và a chiamare join su ognuno di essi la tiene occupata finchè non termina il thread, ma intando altri thread cercano di inserirsi, quindi ConcurrentModificationException Ultima modifica di 13ciccio87 : 25-01-2014 alle 20:22. |
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Mar 2012
Messaggi: 33
|
Mi autorispondo con una soluzione che ho trovato online, ma spero non sia troppo "grezza".
In sostanza, dopo che ho avviato il thread padre scrivo: Codice:
while(Thread.activeCount() > 1){}
Così sembra funzionare, dato che ho lancitato una esecuzione controllata avviando 14 thread (totali). Secondo voi è troppo grezzo? Credo che proverò a fare dei test per vedere se funziona a casaccio o è sempre vero... |
|
|
|
|
|
#5 |
|
Member
Iscritto dal: Oct 2013
Messaggi: 158
|
scusate, qual'e la differenza tra un processo e un thread?
|
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2791
|
La differenza fondamentale è che uno è parte dell'altro, un processo può essere composto da uno o più thread. Da questo poi derivano altre differenze. Ti consiglio di leggere il paragrafo sull'argomento su wikipedia: http://it.wikipedia.org/wiki/Process...cessi_e_thread
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
@13ciccio87
Quel metodo, oltre ad essere "grezzo", sta li a trasformare la tua CPU in una stufetta. Prima di tutto devi utilizzare un metodo synchronized per evitare update concorrenti: http://docs.oracle.com/javase/tutori.../syncmeth.html Secondo, invece di utilizzare una lista, è sufficiente una variabile intera che viene incrementata per ogni thread avviato e decrementata per ogni thread terminato. Terzo, utilizza il metodo wait per bloccare l'esecuzione del thread principale, e il metodo notify per sbloccarlo quando il contatore arriva a zero. |
|
|
|
|
|
#8 |
|
Member
Iscritto dal: Mar 2012
Messaggi: 33
|
Grazie, ma hai risposto al secondo post parlando del primo. Il primo punto lo conosco perfettamente, quando eclipse mi ha avvertito che c'era una modifica concorrente sapevo di dover usare un synchronized. Punto secondo avevo già usato il contatore e inutile dirti che arriva a zero anche quando non sono terminati tutti i thread (altrimenti non stavo qua a usare liste e altre cose), infatti, con il contatore avevo trovato una soluzione ottimale, mi bastava chiedere se ogni volta che decrementavo il contatore era arrivato a zero, purtroppo arriva a zero prima che i thread siano terminati tutti. Per terzo è una buona idea, ma la risposta sta nel punto due.
Per ora, la soluzione "grezza" del wihile sembra funzionare alla grande, l'unico problema è che durante il time slice dedicato al thread che contiene il while consumo il tempo di CPU a fare cicli inutili. Il contatore sarebbe l'idea migliore, ma non riesco a farlo funzionare. |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: May 2008
Città: Seattle (WA)
Messaggi: 306
|
Quote:
__________________
"Considerate la vostra semenza fatti non foste a viver come bruti ma per seguir virtute e canoscenza" |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
La soluzione del contatore ti posso assicurare che funziona, l'ho già utilizzata in passato, se a te non va probabilmente non l'hai implementata correttamente.
Il contatore deve essere unico, un buon posto dove dichiararlo sarebbe nella classe dove si trova il thread principale. Nella stessa classe definisci anche i metodi pubblici incrementa e decrementa, in modo da avere una gestione centralizzata. Dichiara il contatore privato e i metodi synchronized pubblici, così sei sicuro che il contatore venga modificato sempre da un unico thread alla volta. Inoltre, se la tua applicazione lo consente, può essere conveniente dichiarare i metodi static (e di conseguenza anche il contatore), in modo da non dover passare ai thread l'istanza sulla quale invocare i metodi. Ricordati di gestire anche il caso in cui un thread termini inaspettatamente, altrimenti il contatore non arriverà mai a zero. |
|
|
|
|
|
#11 |
|
Member
Iscritto dal: Mar 2012
Messaggi: 33
|
Ovviamente non posso che dare ragione a voi, mi riesco sempre a perdere nelle banalità e poi dico fesserie.
Il contatore lo mettevo nel thread, ma incrementarlo nel thread è sbagliato, perché potrei avere casi in cui un thread non viene avviato in tempo e quindi non incremento il contatore. Mettendo l'incremento nel costruttore del thread (e il decremento prima del break che termina il while(true))ora funziona bene. La soluzione dell'activeCount non mi piaceva perché avrei contato i thread totali e non quelli che servivano a me (quindi non avrei potuto avviare altri thread). Purtroppo non posso usare i metodi (e variabili) static perché la classe contiene altri metodi che dovrei far divenire static (riflettero sul farlo o meno, voi dite che conviene più lo static per non portarmi appresso il peso del collegamento alla classe?). Comunque ora va, ed è questo l'importante. Ultima modifica di 13ciccio87 : 27-01-2014 alle 12:02. |
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
Non c'è bisogno di dichiarare la classe static per avere proprietà e metodi statici, le due cose possono coesistere.
Comunque io l'incremento non lo metterei nel costruttore, perché non è quello il momento in cui il thread parte; lo metterei invece nel metodo run: Codice:
public void run() {
try {
Principale.incrementa();
//CODICE
} catch (Throwable e0) {
} finally {
Principale.decrementa();
}
}
|
|
|
|
|
|
#13 |
|
Member
Iscritto dal: Mar 2012
Messaggi: 33
|
Quando dissi che il contatore non funzionava era proprio perché lo mettevo nel run.
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
Ah, ho capito cosa intendi, però assicurati di incrementare il contatore dopo la chiamata al metodo start, perché se questo genera un'eccezione ti ritrovi il contatore incrementato senza che il thread venga creato. Nel metodo run metti sempre chatch Throwable e il decremento nel finally, altrimenti in caso di eccezione rischi di non decrementare il contatore.
|
|
|
|
|
|
#15 | |
|
Member
Iscritto dal: Mar 2012
Messaggi: 33
|
Quote:
|
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 05:21.




















