如何在无限循环中替换Thread.sleep()?

时间:2014-08-05 13:13:59

标签: java multithreading

我的main中有一个无限循环,它运行一个也是无限循环的作业,并等待它抛出错误。然后它会睡眠一段时间并再次开始任务。

public static void main(String[] args) {
    while (true) {
        try {
            MyClass myClass = new MyClass();
            myClass.startInfiniteLoop();
        }
        catch (SomeException ex) {
            try {
                Thread.sleep(MyClass.DEFAULT_SLEEP_TIME);
            }
            catch (InterruptedException ex2) {
                System.exit(-1);
            }
        }
    }
}

这很好用,但我想知道这是否可以做得更好,可能是ExecutorService因为我(和我的IDE)不喜欢Thread.sleep()循环中的while (true)

我已经阅读了很多关于ScheduledExecutorService和任务管理的问题及其答案,但我没有找到这个特殊情况,因为它不是真正的时间表,我不知道是否以及何时进行任务结束。

2 个答案:

答案 0 :(得分:3)

您可以使用ScheduledExecutorService

ScheduledExecutorService s=Executors.newScheduledThreadPool(1);
s.scheduleWithFixedDelay(new Runnable() {
  public void run() {
    try {
      MyClass myClass = new MyClass();
      myClass.startInfiniteLoop();
    } catch(SomeException ex) {}
  }
}, 0, MyClass.DEFAULT_SLEEP_TIME, TimeUnit.MILLISECONDS);

关键点是使用scheduleWithFixedDelay而不是scheduleAtFixedRate来确保之间的指定的时间与后续执行一样,就像使用sleep方法一样。但请注意,即使使用“固定费率”,新执行也不会在旧执行尚未完成时启动。 It’s documentation说:“如果此任务的执行时间超过其周期,则后续执行可能会延迟,但不会同时执行。

进一步请注意,您仍然需要像我的代码示例中那样捕获异常,否则执行程序将在抛出未捕获的异常后取消计划任务。

答案 1 :(得分:0)

如果您可以使用MyClass并将其重新编写为具有Runnable,该Runnable只执行MyClass的一次循环迭代,那么您可以使用调度执行程序服务,告诉服务每次运行Runnable一次

---根据快速示例的要求更新---

以下不是严格正确的Java代码,它是pesudo-java。

 public class MyRepeatingTask implements Runnable {

    private final ScheduledThreadpoolExecutor executor;

    public MyRepeatingTask(ScheduledThreadpoolExecutor executor) {
      this.executor = executor;
    }

    public void run() {
      try {
        doMyVariableLengthThing();
        // alternatively, you could also schedule a new instance
        executor.schedule(this, 1, TimeUnit.SECONDS);
      } catch (Exception e) {
        cleanup();
      }
    }
 }

然后开始滚球

 ScheduledThreadpoolExecutor executor = new ScheduledThreadpoolExecutor(1);

 executor.execute(new MyRepeatingTask(executor));