定期重复调用函数的一种优雅方式

我经常编写使用一个框架的软件,该框架中每秒调用多次回调方法,但是在该回调内部,我只想每N秒执行一些操作。所以我经常这样做:

int lastMethodCallTime = 0;
int methodRunIntervalMs = 5000;
void methodThatGetsCalledManyTimesPerSecond(){
   int currentTime = getcurrentTime();
   if(currentTime - lastMethodCallTime >= methodRunIntervalMs){
      lastMethodCallTime = currentTime;
      myMethod();
   }
}

但是很可恶。这很丑陋,需要声明外部变量并且非常容易发生错误(很多时候我忘记了lastMethodCallTime = currentTime;,然后想知道为什么它被这么多次调用了)。而且,如果您有多个以不同间隔调用的方法,那么这种丑陋只会成倍增加。

肯定有更优雅的方法吗?我正在寻找一种可以用任何语言实现的想法。而且,在很多情况下,将方法调用置于单独的线程中也不是一种选择,因此我需要在这些约束内进行工作。

qq11220 回答:定期重复调用函数的一种优雅方式

这个答案不是很笼统。我在Java中提供了一个建议,您可能会看到是否可以将其适应于所使用的其他语言。我正在使用一些Java功能。

此外,我无法编写比您已经完成的代码精美的代码。我的建议是应用Bjarne Stroustrup编写的内容:只要您可以将代码隐藏在漂亮的界面后面,代码就可以很丑陋。这将使您可以像这样编写示例代码:

CallFrequencyController myCallFrequencyController
        = new CallFrequencyController(5,TimeUnit.SECONDS,this::myMethod);

void methodThatGetsCalledManyTimesPerSecond() {
    myCallFrequencyController.call();
}

这是我隐藏丑陋代码的地方:

class CallFrequencyController {

    Instant nextCallTime = Instant.now();
    final long methodRunIntervalNanos;
    final Runnable methodToCall;

    public CallFrequencyController(int frequency,TimeUnit frequencyUnit,Runnable methodToCall) {
        methodRunIntervalNanos = frequencyUnit.toNanos(frequency);
        this.methodToCall = methodToCall;
    }

    public void call() {
        Instant now = Instant.now();
        if (now.isBefore(nextCallTime)) {
            return;
        }

        methodToCall.run();

        nextCallTime = now.plusNanos(methodRunIntervalNanos);
    }

}

您可以开发一次该类并进行全面测试,然后您不必担心忘记更新上一个或下一个通话时间或编写其他错误。

如果您需要将参数传递给myMethod并将其结果返回给您的框架,则需要您的类是通用的。这又是一个复杂的问题,但又是一个麻烦:它大部分都隐藏在漂亮的界面后面。是的,该接口是通用的,但是很好,尤其是使用该接口的代码看起来很不错。并发症隐藏在它的后面。

本文链接:https://www.f2er.com/3136367.html

大家都在问