Java 等待线程创建并跳过已完成执行的线程

Java 等待线程创建并跳过已完成执行的线程,java,multithreading,Java,Multithreading,我有4个线程,比如A、B、C和D。 D依赖于所有3个线程。A、 B和C。 它应该只在所有其他3个线程完成执行后启动 D的运行方法 public void run() { for ( final String name : nameList ) { final Thread thread = getThreadByName( name ); if ( thread != null ) {

我有4个线程,比如A、B、C和D。 D依赖于所有3个线程。A、 B和C。 它应该只在所有其他3个线程完成执行后启动

D的运行方法

    public void run() {

            for ( final String name : nameList ) {
                final Thread thread = getThreadByName( name );
                if ( thread != null ) {
                    while ( thread.isAlive() ) {
                        thread.join();
                    }
                }

            }
       //Do something
     }
名称列表包含线程A、B和C的名称

按名称获取线程方法如下所示

public Thread getThreadByName( String threadName ) {
    for ( final Thread t : Thread.getAllStackTraces().keySet() ) {
        if ( t.getName().equals( threadName ) ) {
            return t;
        }
    }
    return null;
}
在我的例子中,线程A已经执行,线程B正在进行中,线程C还没有提交

提交线程D时,它尝试按名称获取线程A,返回null,然后跳过它并尝试按名称获取线程B,返回线程B。线程D等待B完成,然后检查线程C。
getThreadByName
为C返回null,因为C的线程尚未提交。线程D跳过它并开始执行
//Do something

我希望线程D也等待线程C。 它应该跳过线程A,因为它已完成。 等待正在执行的线程B。 但它也应该等待线程C


如何做到这一点?

for的循环只在数据集上迭代一次。你需要一些不同的东西;像这样:

Set<String> threadsToMonitoryByName = ... 

while (! threadsToMonitoryByName.empty() ) {
  for (String threadName : threadsToMonitorByName) { 
     Thread thread = getThreadByName( threadName );
       if ( thread != null ) {
         while ( thread.isAlive() ) {
            thread.join();
            threadsToMonitorByName.remove(threadName);
         }
      }
  }
  // and probably some thread sleeping here to avoid HOT waiting
  ...
}
设置threadsToMonitoryByName=。。。
而(!threadsToMonitoryByName.empty()){
对于(字符串threadName:threadsToMonitorByName){
Thread-Thread=getThreadByName(threadName);
if(线程!=null){
while(thread.isAlive()){
thread.join();
threadsToMonitorByName.remove(threadName);
}
}
}
//可能是一些线程睡在这里,以避免热等待
...
}
换句话说:你必须跟踪那些处理得很好的线程;还有那些还没有准备好处理的

注意:首先,上面的内容更像是“伪代码”,旨在让您继续。可能有许多方面需要仔细检查,例如:

  • 在封闭的while循环中使用该for循环只是其中一种方法。您也可以选择字符串列表的第一个元素;就这样做吧。这里有很多选择
  • 我不确定你是否可以迭代该集合的条目。。。同时,从集合中删除元素
  • 正如HRgiger所指出的:在调用join()之前,您可能不需要对isAlive()进行检查
  • 问题可能最大:您的
    getThreadByName()
    方法看起来像是一个肮脏、昂贵的黑客。如果跟踪你的线程在你的设计中很重要,那么你应该为此创建一个真正的设计。例如,您的线程可能使用一个中央注册表,该注册表保存一个简单的
    映射
    ,以便进行快速、定义良好的查找

  • for
    循环只在数据集上迭代一次。你需要一些不同的东西;像这样:

    Set<String> threadsToMonitoryByName = ... 
    
    while (! threadsToMonitoryByName.empty() ) {
      for (String threadName : threadsToMonitorByName) { 
         Thread thread = getThreadByName( threadName );
           if ( thread != null ) {
             while ( thread.isAlive() ) {
                thread.join();
                threadsToMonitorByName.remove(threadName);
             }
          }
      }
      // and probably some thread sleeping here to avoid HOT waiting
      ...
    }
    
    设置threadsToMonitoryByName=。。。
    而(!threadsToMonitoryByName.empty()){
    对于(字符串threadName:threadsToMonitorByName){
    Thread-Thread=getThreadByName(threadName);
    if(线程!=null){
    while(thread.isAlive()){
    thread.join();
    threadsToMonitorByName.remove(threadName);
    }
    }
    }
    //可能是一些线程睡在这里,以避免热等待
    ...
    }
    
    换句话说:你必须跟踪那些处理得很好的线程;还有那些还没有准备好处理的

    注意:首先,上面的内容更像是“伪代码”,旨在让您继续。可能有许多方面需要仔细检查,例如:

  • 在封闭的while循环中使用该for循环只是其中一种方法。您也可以选择字符串列表的第一个元素;就这样做吧。这里有很多选择
  • 我不确定你是否可以迭代该集合的条目。。。同时,从集合中删除元素
  • 正如HRgiger所指出的:在调用join()之前,您可能不需要对isAlive()进行检查
  • 问题可能最大:您的
    getThreadByName()
    方法看起来像是一个肮脏、昂贵的黑客。如果跟踪你的线程在你的设计中很重要,那么你应该为此创建一个真正的设计。例如,您的线程可能使用一个中央注册表,该注册表保存一个简单的
    映射
    ,以便进行快速、定义良好的查找

  • 您需要运行while循环来使用join吗?这是他的代码;我试着尽可能地匹配。但我会在答案中补充这一点;谢谢
    entries()
    Set
    界面中的方法吗?Java 7中没有列出它:我还担心在对集合进行迭代时修改它。@AndrewHenle非常感谢您。。。这就是我为什么写伪代码的原因。你完全正确,因为这是一个集合,而不是一张地图,一个人只是“走”集合本身。你的第二点已经在我的笔记中提到了。@GhostCat跟踪线程为我工作。我还更改了getThreadByName()方法。谢谢:)使用join需要运行while循环吗?这是他的代码;我试着尽可能地匹配。但我会在答案中补充这一点;谢谢
    entries()
    Set
    界面中的方法吗?Java 7中没有列出它:我还担心在对集合进行迭代时修改它。@AndrewHenle非常感谢您。。。这就是我为什么写伪代码的原因。你完全正确,因为这是一个集合,而不是一张地图,一个人只是“走”集合本身。你的第二点已经在我的笔记中提到了。@GhostCat跟踪线程为我工作。我还更改了getThreadByName()方法。谢谢:)也许
    java.util.concurrent.CountDownLatch
    -我从来没用过它。。。另外,请看一下
    java.util.concurrent.CyclicBarrier
    java.util.concurrent.Semaphore
    。我今天给大家的答案是。。。是朱