有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何替换线程。无限循环中的sleep()?

我的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) 个答案

  1. # 1 楼答案

    您可以使用^{}

    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);
    

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

    进一步注意,您仍然必须像在我的代码示例中那样捕获异常,否则一旦执行者抛出未捕获的异常,它就会取消计划的任务

  2. # 2 楼答案

    如果您可以使用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));