Reputation: 1209
I have a Thread that will run a third party lib which also will run their own Threads. When the run method of my Thread finishes, third party Threads will not be finished yet.
So, what is the best way to hold my Thread until these external Threads are still running?
Upvotes: 6
Views: 464
Reputation: 27115
Maybe not an answer to your question, but if I wrote a library that creates threads, I would
A) Use a ThreadFactory to create them, and provide a means for my client to supply the ThreadFactory instance, and
B) Provide a .shutdown()
method (or some similar name) that cleanly shuts things down, and does not return until all of the threads have died.
I don't know about the library that you're using though.
Upvotes: 0
Reputation: 718778
I have a Thread that will run a third party lib which also will run their own Threads.
@Lawrence Dol's answer explains that you can use ThreadGroup
to traverse the group tree and find all live threads ... provided your application is not sandboxed. You then have the problem of figuring out which threads belong to the 3rd-party library, but there is a good chance that you can do this heuristically; e.g. based on thread names.
But the point I want to make is that a library that fires up background threads to do work, and provides no way to wait for the work to finish is poorly designed:
I'd look at the API spec for the library to see if it already provides its own solution to this; e.g. a "shutdown" method that waits for the worker threads to finish.
If not, then contact the library maintainers and ask them how to deal with the situation. The "workaround" with thread groups is a fragile hack.
If that doesn't yield results, and if the library is open source, consider coding up an API enhancement and submitting it as a patch.
Upvotes: 4
Reputation: 64026
If you are an application and don't have to worry about SecurityManager restrictions, and if you are prepared to occasionally modify your code when the third-party code is updated, you can use the facilities of ThreadGroup
to walk the threads and identify them by name or by the thread group that contains them.
Once you've located the threads it's a simple job to either monitor them until they are done or to use Thread.join()
as appropriate.
As an example, here is some working code which dumps all threads in the 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(" --");
}
Upvotes: 4
Reputation: 76444
Let's consider the creation of a Thread
set, maybe AbstractList<Thread>
. Whenever you create a new Thread
, you add it to your set. When your parent Thread
would like to finish its job, do something like:
for (int i = 0; i < childrenThreads.size(); i++) {
childrenThreads.get(i).join();
}
I understand that this idea, in itself only solves the finalization of the children Threads
, but if you use the same mechanism for the children Thread
s and their children and so on, then the
childrenThreads.get(i).join();
will wait for the i'th child Thread
, which in turn will wait for its child Threads
in a transitive waiting.
Upvotes: 0