2014-12-17 17 views
6

Ho un thread che eseguirà una libreria di terze parti che eseguirà anche i propri thread. Quando termina il metodo run della mia discussione, i thread di terze parti non saranno ancora terminati.Java - Attendi il completamento dei thread di terze parti

Quindi, qual è il modo migliore per tenere il mio thread fino a quando questi thread esterni sono ancora in esecuzione?

+0

Avresti bisogno di un qualche tipo di riferimento da aspettare. Come ad esempio una discussione, un futuro o la possibilità di installare una richiamata. Se la libreria non la espone, sarà difficile ... Forse qualcosa che puoi sondare ogni X secondi? – Thilo

+0

Potrei sondarlo, ma come potrei sapere che sono finiti? Posso "spiare" i fili generati dopo il mio? – bsferreira

+0

Voglio dire sondaggio fino a quando non vedi qualcosa che ti dice che questi thread hanno fatto tutto ciò che devono fare. Sei sicuro che la biblioteca non fornisce supporto per qualche tipo di notifica? Potresti ottenere risposte migliori se puoi dirci di quale biblioteca si tratta. – Thilo

risposta

4

Se si sono un'applicazione e non devono preoccuparsi di restrizioni SecurityManager, e se si sono preparati per modificare di tanto in tanto il codice quando il codice di terze parti viene aggiornato, è possibile utilizzare le strutture di ThreadGroup per eseguire i thread e identificarli in base al nome o al gruppo di thread che li contiene.

Una volta individuati i thread, è semplice controllarli finché non sono terminati o utilizzare Thread.join() in base alle esigenze.

Come esempio, qui è un codice di lavoro che scarica tutte le discussioni nella JVM:

public void printThreads(PrintWriter wtr) { 
    ThreadGroup  root; 

    totGroups=0; 
    totThreads=0; 

    for(root=Thread.currentThread().getThreadGroup(); root.getParent()!=null; root=root.getParent()) {} 
    wtr.println("Thread Dump:"); 
    printThreadGroup(wtr,root," "); 
    wtr.println(" -- Total Groups: "+totGroups+", Total Threads: "+totThreads); 
    } 

public void printThreadGroup(PrintWriter wtr, ThreadGroup grp, String pfx) { 
    try { 
     Thread[]  thds; 
     ThreadGroup[] grps; 

     totGroups++; 
     wtr.println(pfx+"Group: "+grp.getName()+", "+(grp.isDaemon()?"Daemon":"Normal")+", "+(grp.isDestroyed()?"Destroyed":"Alive")+", "+grp.getMaxPriority()); 
     thds=new Thread[grp.activeCount()]; 
     grp.enumerate(thds,false); 
     Arrays.sort(thds,THREAD_SORTER); 
     for(int xa=0; xa<thds.length && thds[xa]!=null; xa++,totThreads++) { 
      Thread   thd=thds[xa]; 
      wtr.println(pfx+". - ["+thd.getName()+", "+(thd.isDaemon()?"Daemon":"Normal")+", "+(thd.isAlive()?"Alive":"Not Started or Dead")+", "+thd.getPriority()+"]"); 
      } 

     grps=new ThreadGroup[grp.activeGroupCount()]; 
     grp.enumerate(grps,false); 
     Arrays.sort(grps,GROUP_SORTER); 
     for(int xa=0; xa<grps.length && grps[xa]!=null; xa++) { 
      printThreadGroup(wtr,grps[xa],(pfx+". ")); 
      grps[xa]=null; 
      } 
     } 
    catch(Throwable thr) { 
     wtr.println(" Cannot print threads ("+thr+")"); 
     } 
    } 

public void printStacks(PrintWriter wtr) { 
    wtr.println("Thread Stack Traces:"); 
    try { javaMx.printStacks(wtr); } catch(Throwable thr) { wtr.println(" Cannot print stacks ("+thr+")"); } 
    wtr.println(" --"); 
    } 
0

Consideriamo la creazione di un set Thread, forse AbstractList<Thread>. Ogni volta che crei un nuovo Thread, lo aggiungi al tuo set. Quando il genitore Thread vorrebbe finire il suo lavoro, fare qualcosa di simile:

for (int i = 0; i < childrenThreads.size(); i++) { 
    childrenThreads.get(i).join(); 
} 

Capisco che questa idea, di per sé risolve solo la finalizzazione dei bambini Threads, ma se si utilizza lo stesso meccanismo per i bambini Thread s ed i loro figli, e così via, allora il

childrenThreads.get(i).join(); 

attenderà il bambino-esimo Thread, che a sua volta attendere per il suo bambino Threads in attesa transitiva.

+0

Capisco cosa stai facendo, ma non sto creando direttamente il bambino. Sto solo dicendo al mio Thread di funzionare e saranno le libs invocate all'interno del metodo run che in realtà creeranno le loro Thread. – bsferreira

4

Ho un filo che verrà eseguito un terzo lib partito che sarà anche eseguire le proprie discussioni.

risposta di @Lawrence Dol spiega che è possibile utilizzare ThreadGroup per attraversare la struttura del gruppo e trovare tutte le discussioni dal vivo ... fornito la vostra applicazione non viene tenuta stagna. Quindi hai il problema di capire quali thread appartengono alla libreria di terze parti, ma c'è una buona possibilità che tu possa farlo in modo euristico; per esempio. in base ai nomi dei thread.

Ma il punto che voglio fare è che una libreria che spara fino thread in background per fare il lavoro, e fornisce un modo per attendere che il lavoro alla fine è mal progettato:

  • mi piacerebbe guardare alle specifiche API per la libreria per vedere se fornisce già la propria soluzione a questo; per esempio. un metodo "shutdown" che attende la fine dei thread worker.

  • In caso contrario, contattare i manutentori della biblioteca e chiedere loro come affrontare la situazione. La "soluzione alternativa" con i gruppi di thread è un trucco modesto .

  • Se ciò non produce risultati e se la libreria è open source, prendere in considerazione la possibilità di codificare un miglioramento dell'API e inviarlo come patch.

0
non

Forse una risposta alla tua domanda, ma se ho scritto una libreria che crea discussioni, vorrei

A) Utilizzare un ThreadFactory per crearli, e fornire un mezzo per il mio cliente per fornire il Istanza ThreadFactory e

B) Fornire un metodo .shutdown() (o un nome simile) che interrompa correttamente le operazioni e non ritorna fino a quando tutti i thread non sono morti.

Non conosco la libreria che si sta utilizzando.

Problemi correlati