Java - 等待第三方线程完成

时间:2014-12-17 01:00:19

标签: java

我有一个运行第三方库的线程,它也将运行自己的线程。当我的线程的run方法完成时,第三方线程将不会完成。

那么,在这些外部线程仍在运行之前,保持我的线程的最佳方法是什么?

4 个答案:

答案 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()方法(或一些类似的名称),干净地关闭事物,并且在所有线程都死亡之前不会返回。

我不知道您正在使用的库。