Java-等待第三方线程完成

Java-等待第三方线程完成,java,Java,我有一个线程将运行第三方库,该库也将运行自己的线程。当我的线程的run方法完成时,第三方线程还没有完成 P>那么,在这些外部线程仍在运行之前保存线程的最佳方法是什么?让我们考虑创建线程集合,也许抽象列表> /COD>。无论何时创建新的线程,都会将其添加到集合中。当您的父线程想完成其工作时,请执行以下操作: for (int i = 0; i < childrenThreads.size(); i++) { childrenThreads.get(i).join(); } 将等待

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


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

让我们考虑创建<代码>线程集合,也许<代码>抽象列表> /COD>。无论何时创建新的

线程
,都会将其添加到集合中。当您的父线程想完成其工作时,请执行以下操作:

for (int i = 0; i < childrenThreads.size(); i++) {
    childrenThreads.get(i).join();
}
将等待第i个子
线程
,而第i个子
线程将在传递等待中等待其子
线程。

如果您是一个应用程序,不必担心安全管理器限制,如果您准备在更新第三方代码时偶尔修改代码,则可以使用
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("  --");
    }
公共无效打印线程(PrintWriter wtr){
线组根;
两组总人数=0;
总线程数=0;
对于(root=Thread.currentThread().getThreadGroup();root.getParent()!=null;root=root.getParent()){}
println(“线程转储:”);
printThreadGroup(wtr,根“”);
wtr.println(“--Total Groups:+totGroups+”,Total Threads:+tottthreads);
}
public void printThreadGroup(PrintWriter wtr、ThreadGroup grp、String pfx){
试一试{
线程[]thds;
线程组[]GRP;
totGroups++;
wtr.println(pfx+“组:“+grp.getName()+”,“+(grp.isDaemon()?”守护进程“:“正常”)+,“+(grp.isDestroyed()?”已销毁“:“活动”)+,“+grp.getMaxPriority()”;
thds=新线程[grp.activeCount()];
grp.枚举(thds,假);
阵列。分拣(thds、线程分拣机);
对于(int xa=0;xa
我有一个线程将运行第三方库,该库也将运行自己的线程

@Lawrence Dol的回答解释说,你可以使用
ThreadGroup
遍历组树并找到所有活动线程…前提是你的应用程序没有沙盒。然后你就有了确定哪些线程属于第三方库的问题,但你很有可能通过启发式的方法来完成这项工作;例如,基于thre广告名称

但我想指出的一点是,一个启动后台线程来执行工作,并且不提供等待工作完成的方法的库设计得很糟糕:

  • 我会查看库的API规范,看看它是否已经提供了自己的解决方案;例如,一个等待工作线程完成的“shutdown”方法

  • 如果没有,请联系库维护人员,并询问他们如何处理这种情况。线程组的“变通方法”是一种脆弱的攻击

  • >P>如果不产生结果,如果库是开源的,请考虑编码API增强并提交它作为补丁。


      也许不是你问题的答案,但如果我写了一个创建线程的库,我会

      A) 使用ThreadFactory创建它们,并为我的客户端提供提供ThreadFactory实例的方法,以及

      B) 提供一个
      .shutdown()
      方法(或类似的名称),该方法可以干净地关闭所有线程,并且在所有线程都死掉之前不会返回


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

      您需要等待某种引用。例如线程、未来或安装回调的可能性。如果库不公开,这将很难……也许您可以每隔X秒轮询一次?我可以轮询,但我如何知道它们已完成?我可以“间谍”吗在我之后生成的线程?我的意思是轮询,直到你看到一些东西告诉你这些线程已经完成了它们需要做的任何事情。你确定库没有提供对某种通知的支持吗?如果你能告诉我们这是什么库,你可能会得到更好的答案。我理解你在做什么,但我没有创建chi我只是告诉我的线程运行,在run方法中调用的libs实际上将创建它们自己的线程。
      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("  --");
          }