peixaxo Ответов: 0

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

Кажется, что-то не так с кодом?
По отношению к чему? Вы понимаете, что это не будет приложение реального времени, поэтому Дельта-время всегда будет произвольным, в зависимости от того, что еще работает в системе.

0 Ответов