【问题标题】:Thread waiting logic线程等待逻辑
【发布时间】:2016-02-22 17:48:44
【问题描述】:

我有一个只有一组字符串的对象。我可以随时向字符串添加名称。我将 5 秒设置为完成添加要设置的名称的最大等待时间。之后,我将打印集合中的所有名称。所以我为我的对象定义了以下类。

public class FamilyGroup {
    Set<String> names;
    private long id;

    public FamilyGroup(long id) {
        this.id = id;
        names = new HashSet<String>();
    }

    public void addName(String name) {
        names.add(name);
    }

    public void displayFamilyMembers() {
        for (String string : names) {
            System.out.println(string);
        }
    }
}

我正在将此作业提交给 Runnable,如下所示,

public class FamilyWaiterThread implements Runnable {
    private FamilyGroup group;
    private final long MAX_WAITING_TIME = 1000 * 15;

    FamilyWaiterThread(FamilyGroup group) {
        this.group = group;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(MAX_WAITING_TIME);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        group.displayFamilyMembers();
    }
}

此代码等待 15 秒,然后成功打印集合中的所有名称。这就是我正在测试它的方式。

public class FamilyTest {
    public static void main(String[] args) throws InterruptedException {
        FamilyGroup familyGroup1 = new FamilyGroup(1L);
        familyGroup1.addName("Shane Lee");
        FamilyWaiterThread familyWaiterThread1 = new FamilyWaiterThread(familyGroup1);
        new Thread(familyWaiterThread1).start();
        Thread.sleep(2000);
        familyGroup1.addName("Bret Lee");
    }
}

我在生成新线程 2 秒后添加名称“Bret Lee”,该新线程等待 15 秒并打印两个名称。输出是

Shane Lee
Bret Lee

假设我在 16 秒后添加名称“Bret Lee”,

Thread.sleep(16000);
familyGroup1.addName("Bret Lee");

它只打印“Shane Lee”,因为线程只等待 15 秒。 现在我想再添加一项功能。如果连续 5 秒没有添加名称,我希望线程停止等待并打印输出。如果在 5 秒内添加了任何名称,则线程应继续最多侦听 15 秒。总而言之,我对组对象的最长等待时间是 15 秒。 15 秒后,我肯定会打印输出,如果至少 5 秒内没有添加名称,我将打印输出。我想不出办法来实现这一点。欢迎任何想法,因为我是多线程的新手。

【问题讨论】:

  • 您正在寻找的概念称为Watchdog Timer。在 FamilyGroup 的构造函数中,您创建了两个看门狗定时器:第一个周期为 15 秒,第二个周期为 5 秒。每次添加名称时都会重置后者。第一个计时,打印名称。 注意您需要适当的同步原语以避免数据竞争。

标签: java multithreading


【解决方案1】:

作为一个非常简单的解决方案,您可以在 FamilyGroup 类中使用一个标志来指示是否已插入新数据。类似public boolean HasSomethingNew = false 的东西在addName() 方法中设置true 并在displayFamilyMembers 方法中设置false
然后你需要像这样在你的线程run方法中循环

@Override
public void run() {
    boolean EndThread = false;
    int WaitingRuns = 0;
    while(!EndThread){
        while(!group.HasSomethingNew && WaitingRuns < 3){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            WaitingRuns++;
        }
        if(group.HasSomethingNew){
            group.displayFamilyMembers();
            WaitingRuns = 0;
        } else EndThread = true;
    }
}

【讨论】:

    【解决方案2】:

    这是FamilyWaiterThread。我添加了一个变量名为 second(second thread) 的 Thread 实例 ..

    在 set 打印 15 秒后,第二个 Threadstarts... 如果 add 方法没有停止它,它会运行 5s。

    谢谢...好问题顺便说一句...!!

    public class FamilyWaiterThread implements Runnable {
    private FamilyGroup group;
    private final long MAX_WAITING_TIME = 1000 * 15;
    Thread second = new Thread()
        {
            public void run()
            {
                try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
                System.out.println("Before adding");
                group.displayFamilyMembers();
            }
        };
    FamilyWaiterThread(FamilyGroup group) {
        this.group = group;
    }
    FamilyWaiterThread(){}
    
    @Override
    public void run() {
            try {
                Thread.sleep(MAX_WAITING_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        group.displayFamilyMembers();
        second.start();
    }
     }
    

    这是 FamilyGroup 中的小变化

    public void addName(String name) {
        names.add(name);
        new FamilyWaiterThread().second.stop();
    }
    

    【讨论】:

      【解决方案3】:

      最后我能够得到想要的输出。谢谢大家!!

      public class FamilyWaiterThread implements Runnable {
          private FamilyGroup group;
          private boolean hasSomthingNew = true;
          private final long MAX_WAITING_TIME = 1000 * 10;
          private final long MAX_INACTIVE_TIME = 1000 * 3;
      
          FamilyWaiterThread(FamilyGroup group) {
              this.group = group;
          }
      
          public boolean hasSomethingNew() {
              return hasSomthingNew;
          }
      
          public void setHasSomethingnew(boolean value) {
              hasSomthingNew = value;
          }
      
          @Override
          public void run() {
              long startTime = System.currentTimeMillis();
              while (!timeOut(startTime) && hasSomethingNew()) {
                  hasSomthingNew = false;
                  long currentTime = System.currentTimeMillis();
                  if (((startTime + MAX_WAITING_TIME) - currentTime) < MAX_INACTIVE_TIME) {
                      break;
                  }
                  try {
                      Thread.sleep(MAX_INACTIVE_TIME);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              long afterWhileLoop = System.currentTimeMillis();
              System.out.println("Total waiting time " + (afterWhileLoop - startTime));
              group.displayFamilyMembers();
              System.out.println("__________________________________");
          }
      
          private boolean timeOut(long startTime) {
              long currentTime = System.currentTimeMillis();
              if ((currentTime - startTime) > MAX_WAITING_TIME) {
                  return true;
              }
              return false;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-18
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        • 1970-01-01
        相关资源
        最近更新 更多