Java-пользовательский планировщик задач очень неточен
Я хочу построить очень простой, но эффективный планировщик, к которому классы, реализующие интерфейс SchedulerListener (для запущенных/завершенных событий), регистрируются с тем, сколько секунд и/или миллисекунд должен ждать планировщик, чтобы уведомить их (через завершенное событие).
Когда запрос завершен, отдельный объект получает уведомление и вычисляет разницу между временем начала и окончания, которое затем сравнивается с ранее зарегистрированным "ожидаемым временем", чтобы узнать разницу.
Обычно различия варьируются от 0 до 20 миллисекунд.
Проблема заключается в том, что различия проявляются как отрицательные - это означает, что задача завершилась до того времени, когда она должна была пройти.
Планировщик работает в отдельном потоке.
Кажется, что-то не так с кодом?
Примечание: первоначально запросы хранились в ArrayList, и задержки иногда доходили до 30 мс, но ничего плохого вообще не было. В попытке уменьшить это значение Я заменил ArrayList на ConcurrentHashMap (чтобы избежать исключений во время итерации), что действительно снижает задержку, хотя и вызывает указанную проблему.
Что я уже пробовал:
Логика планировщика проста. Я использую механику Дельта-времени, уменьшающую каждый запрос (в миллисекундах) на дельтатим каждого "кадра" и отменяющую регистрацию запроса после того, как прошло соответствующее время (или больше).
Я не буду публиковать весь код, чтобы не перегружать вопрос, если это не нужно.
Код планировщика
public void registerListener(SchedulerListener listener, long seconds, long milliseconds) { if(!isRunning) return; listener.onSchedulerStart(); listeners.put(listener, secondsToMilliseconds(seconds) + milliseconds); } public void unregisterListener(SchedulerListener listener) { if(!isRunning) return; listeners.remove(listener); public void run() { isRunning = true; long lastTime, currentTime, deltaTime; lastTime = System.currentTimeMillis(); while(!Thread.currentThread().isInterrupted()) { currentTime = System.currentTimeMillis(); deltaTime = currentTime - lastTime; checkRequests(deltaTime); lastTime = currentTime; } } private void checkRequests(long deltaTime) { long value; for(SchedulerListener listener : listeners.keySet()) { value = listeners.get(listener) - deltaTime; listeners.put(listener, value); if(value <= 0) { listener.onSchedulerDone(); listeners.remove(listener); } } }
Richard MacCutchan
Кажется, что-то не так с кодом?
По отношению к чему? Вы понимаете, что это не будет приложение реального времени, поэтому Дельта-время всегда будет произвольным, в зависимости от того, что еще работает в системе.