Подтвердить что ты не робот

Перезапуск службы с использованием Guava

В настоящее время я разрабатываю приложение, в котором мне нужно управлять состоянием нескольких служб и останавливать/запускать их на основе некоторых событий. Проблема заключается в том, что, как указано в документах, служба Guava является однонаправленной, то есть после ее остановки ее нельзя запустить снова.

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

Первым очевидным решением этой проблемы является создание новой службы, когда мне нужно "перезапустить" ее. Это работает, но в моей нынешней архитектуре это немного усложнит ситуацию: в настоящее время я устанавливаю все службы и основываюсь на событиях из EventBus, запуская или останавливая их, если это необходимо. Класс, который вызывает методы start и stop, сохраняет только ссылку на карту сервисов и вызывает правильный метод в этих экземплярах на основании полученного события. Если мне нужно создать экземпляр нового объекта в ответ на Событие, мне придется отказаться от некоторой де-связи, которая у меня есть (возможно, сохраняя класс каждого типа Сервиса и вызывая конструктор с использованием отражения).

Другая возможность - реализовать интерфейс службы как RestartableThreadedService (или что-то в этом роде). Если бы я взял этот маршрут, мой метод start() мог бы создать другой поток, как если бы это был первый раз, и reset состояния.

Есть ли какой-либо явный недостаток для второго подхода? Я боюсь, что у меня может возникнуть некоторый очевидный недостаток (помимо того, что нужно что-то немного усложнять), особенно в отношении управления потоками.

4b9b3361

Ответ 1

Я бы рекомендовал ваш первый подход, но есть лучшие способы сделать это, чем размышления. Использование инъекции зависимостей или, возможно, передача объектов Supplier<Service> вместо использования serviceClass.newInstance(), вероятно, путь сюда.

Ответ 2

Рассмотрим использование областей Guice.

Ответ 3

Эта же проблема отслеживается в этом github: https://github.com/google/guava/issues/418

У меня есть предлагаемое изменение здесь: https://github.com/okigan/guava/commit/8f51b155f9ce5c60236b9a9bfdc6ca5f8bf5e51d

суть состоит в том, чтобы добавить reset() в AbstractService что позволяет перейти от TERMINATED обратно в NEW:

    public final void reset() {
    lock.lock();
    try {
        switch (snapshot.state) {
            case TERMINATED:
            case FAILED:
                snapshot = new StateSnapshot(State.NEW);
                break;
            default:
                throw new AssertionError("Unexpected state: " + snapshot.state);
        }
    } catch (Throwable resetFailure) {
        notifyFailed(resetFailure);
    } finally {
        lock.unlock();
        executeListeners();
    }
}