2

最近我编写了必须限制请求吞吐量的代码。我用过ScheduleExecutorService.scheduleAtFixedRate并且我相信它应该可以完成工作(它确实做到了!)但是我写了一些测试来检查计划任务的时间,我很惊讶。最初的几个任务没有像 javadoc 用 n*period 解释的那样安排。谁能解释我错过了什么?如果它以这种方式工作,那么为什么 javadoc 中没有提到它?然后问题是调度程序究竟是如何工作的?我想避免寻找来源:)

例子:

import java.time.Duration;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class ExecutorTest {
    Executor executor;
    ScheduledExecutorService schedulingExecutor;
    BlockingQueue<LocalTime> times;

    public static void main(String[] args) throws InterruptedException {
        new ExecutorTest().start();
    }

    public ExecutorTest() {
        schedulingExecutor = Executors.newScheduledThreadPool(1);
        executor = Executors.newCachedThreadPool();
        times = new LinkedBlockingQueue<>();
    }

    public void start() throws InterruptedException {
        schedulingExecutor.scheduleAtFixedRate(this::executeTask, 0, 50, TimeUnit.MILLISECONDS);
        LocalTime nextEvaluatedTime = times.take();
        LocalTime time = nextEvaluatedTime;

        while (true) {
            System.out.println(String.format(String.join(" ", "recorded time: %d", "calculated proper time: %d", "diff: %d"),
                                      time.toNanoOfDay(),
                                      nextEvaluatedTime.toNanoOfDay(),
                                      Duration.between(nextEvaluatedTime, time).toNanos()));
            nextEvaluatedTime = time.plus(50, ChronoUnit.MILLIS);
            time = times.take();
        }
    }

    private void executeTask() {
       executor.execute(() -> {
          times.add(LocalTime.now());
       });
    }
}

如果你运行这个程序,你会发现很少有第一次没有按预期记录。为什么?

4

0 回答 0