Java: вызвать событие, если метод не был вызван в течение определенного времени - PullRequest
0 голосов
/ 30 мая 2018

В параллельной среде несколько потоков вызывают метод.После того, как метод не был вызван в течение некоторого времени (например, 5 секунд), должно быть вызвано событие простоя.

Еще через 5 секунд без вызова метода событие простоя не должно вызываться снова.Таймер простоя должен быть снова запущен после первого вызова метода.

public class Service {
    public void do(Foo foo) {
        // process foo
    }

    private void onIdle() {
    }
}

Какой безопасный и эффективный способ реализовать это?

Если это можно сделать намного лучше без второго требования(не вызывая onIdle () снова и снова), тогда это будет приемлемо.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Разделите проблемы.Позвольте службе сохранить состояние вызова и попросить другой поток опрашивать метод ожидания:

public class Service {
    private volatile long lastActivity;
    public void do(Foo foo) {
        // process foo
        lastActivity = System.currentTimeMillis();
    }

    private void onIdle() {
        if (lastActivity > 0 && System.currentTimeMillis() - lastActivity > 5000) {
            // do stuff
            lastActivity = 0;
        }
    }
}

Затем запускать задачу каждые 5 секунд в другом потоке, который просто выполняет:

public void run() {
    service.onIdle();
}

Выможете запланировать задачу, используя все, что ваша среда предоставляет из коробки (например, Spring @Scheduled), или создать свой собственный поток, который просто спит через 5 секунд после вызова onIdle () в while (true) Koop.

0 голосов
/ 30 мая 2018

Если вы можете позволить себе выделять поток только для просмотра вашего сервиса, вот реализация.

Гарантия этого кода в том, что в любое время не может быть более одного активного наблюдателя;и если клиент вызывает onCall, после этого вызова всегда будет живой наблюдатель.

(в любом случае, обратите внимание, что для простоты кода (во избежание повторения проверок) он все равно будет возможенчтобы клиент вызывал метод onCall () в тот момент, когда истекает срок действия наблюдателя, и наблюдатель мог бы сразу же после этого вызвать очистку. Таким образом, у нас было бы время = 0 между вызовом клиента и операцией очистки.вызов клиента, другой наблюдатель будет спамить)

package stackOverflow;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Service {

  private ServiceWatch watch = new ServiceWatch(this::onIdle, 5000L);

  public void compute() {
    // business here
    // and notify the watcher
    watch.onCall();
  }

  private void onIdle() {
    // cleanup here, will be executed by the watcher
  }
}


class ServiceWatch {
  boolean started;
  volatile long lastCallTime;
  private Runnable onIdle;
  private long maxIdle;

  private ExecutorService es = Executors.newSingleThreadExecutor();

  public ServiceWatch(Runnable onIdle, long maxIdle) {
    this.onIdle = onIdle;
    this.maxIdle = maxIdle;
  }

  public synchronized void onCall() {
    lastCallTime = System.currentTimeMillis();
    if (!started) {
      startWatcher();
      started = true;
    }
  }

  // spawns a worker-watcher
  public void startWatcher() {
    es.submit(
        new Runnable() {

          private void triggerIdle() {
            synchronized (ServiceWatch.this) {
              onIdle.run();
              started = false;
            }
          }

          @Override
          public void run() {
            long toSleep;
            do {
              toSleep = getSleepTime();
              if (toSleep > 0) {
                try {
                  Thread.sleep(toSleep);
                } catch (InterruptedException e) {
                  triggerIdle();
                  toSleep = 0;
                }
              } else {
                triggerIdle();
              }
            } while (toSleep>0);
          }
        });
  }

  private long getSleepTime() {
    return (lastCallTime + maxIdle) - System.currentTimeMillis();
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...