最近、リクエストのスループットを制限しなければならないコードを書きました。私は使用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());
});
}
}
このプログラムを実行すると、期待どおりに記録されなかった初回がほとんどないことがわかります。なんで?