简体   繁体   English

Java - 等待第三方线程完成

[英]Java - Wait for third party threads to finish

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. 当我的线程的run方法完成时,第三方线程将不会完成。

So, what is the best way to hold my Thread until these external Threads are still running? 那么,在这些外部线程仍在运行之前,保持我的线程的最佳方法是什么?

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. 如果您是一个应用程序而不必担心SecurityManager限制, 并且如果您准备在更新第三方代码时偶尔修改代码,则可以使用ThreadGroup来遍历线程并通过以下方式识别它们:名称或包含它们的线程组。

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. 一旦找到了线程,就可以在它们完成之前监视它们,或者在适当的时候使用Thread.join()

As an example, here is some working code which dumps all threads in the JVM: 举个例子,这里有一些工作代码转储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("  --");
    }

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. @Lawrence Dol的回答解释说,如果您的应用程序没有沙盒,您可以使用ThreadGroup遍历组树并查找所有活动线程。 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; 然后你有问题找出哪些线程属于第三方库,但很有可能你可以启发式地做到这一点; eg 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; 我会查看该库的API规范,看看它是否已经为此提供了自己的解决方案; eg 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. 如果这不会产生结果,并且库是开源的,请考虑编写API增强功能并将其作为补丁提交。

Let's consider the creation of a Thread set, maybe AbstractList<Thread> . 让我们考虑创建一个Thread集,也许是AbstractList<Thread> Whenever you create a new Thread , you add it to your set. 每当您创建新Thread ,都会将其添加到您的集合中。 When your parent Thread would like to finish its job, do something like: 当您的父Thread想要完成其工作时,执行以下操作:

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 我明白这个想法本身只能解决子Threads的最终定义,但是如果你Thread s和它们的子Thread使用相同的机制等等,那么

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. 将等待第一个子Thread ,这反过来将等待其子Threads在传递等待。

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 A)使用ThreadFactory创建它们,并为我的客户端提供一种提供ThreadFactory实例的方法,和

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. B)提供一个干净地关闭东西的.shutdown()方法(或一些类似的名字),直到所有的线程都死掉之后才返回。

I don't know about the library that you're using though. 我不知道你正在使用的图书馆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM