我有一个运行第三方库的线程,它也将运行自己的线程。当我的线程的run方法完成时,第三方线程将不会完成。
那么,在这些外部线程仍在运行之前,保持我的线程的最佳方法是什么?
答案 0 :(得分:4)
如果 您是一个应用程序并且不必担心SecurityManager限制, 以及 您准备在更新第三方代码时偶尔修改代码,您可以使用ThreadGroup
的工具来遍历线程并通过名称或包含它们的线程组来识别它们。
一旦找到线程,就可以在完成之前对其进行监控,或者在适当时使用Thread.join()
。
作为一个例子,这里有一些工作代码转储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(" --");
}
答案 1 :(得分:4)
我有一个运行第三方库的线程,它也将运行自己的线程。
@Lawrence Dol的回答解释说,如果您的应用程序没有沙盒,您可以使用ThreadGroup
遍历组树并查找所有活动线程。然后你有问题找出哪些线程属于第三方库,但很有可能你可以启发式地做到这一点;例如基于线程名称。
但我想说的是,一个启动后台线程来工作的库,并且无法等待工作完成的设计很糟糕:
我要查看该库的API规范,看看它是否已经为此提供了自己的解决方案;例如a&#34;关闭&#34;等待工作线程完成的方法。
如果没有,请联系图书馆维护人员并询问他们如何处理这种情况。 &#34;解决方法&#34;使用线程组是一个脆弱的黑客。
如果这不会产生结果,并且库是开源的,请考虑编写API增强功能并将其作为补丁提交。
答案 2 :(得分:0)
让我们考虑创建一个Thread
集,也许AbstractList<Thread>
。每当您创建新的Thread
时,都会将其添加到您的集合中。当您的父母Thread
想要完成其工作时,请执行以下操作:
for (int i = 0; i < childrenThreads.size(); i++) {
childrenThreads.get(i).join();
}
我理解这个想法本身只能解决孩子Threads
的最终确定,但是如果你对孩子Thread
和他们的孩子使用相同的机制等等,那么< / p>
childrenThreads.get(i).join();
会等待第一个孩子Thread
,而后者会等待其子Threads
进行传递等待。
答案 3 :(得分:0)
也许不是你问题的答案,但如果我写了一个创建线程的库,我会
A)使用ThreadFactory创建它们,并为我的客户端提供一种提供ThreadFactory实例的方法,并且
B)提供一个.shutdown()
方法(或一些类似的名称),干净地关闭事物,并且在所有线程都死亡之前不会返回。
我不知道您正在使用的库。