Цепочка ответственности - обработка более одного запроса - PullRequest
2 голосов
/ 04 ноября 2019

Правильно, мне может быть немного сложно объяснить это, так как я новичок в этом.

Мне дали задание использовать Chain of Responsibility для решения одной из проблем. У меня не было проблем с пониманием и реализацией, пока я не узнал, что должен убедиться, что моя цепочка способна обрабатывать более одного запроса одновременно.

Цепочка, по сути, должна работать следующим образом: во всей цепочке есть две или более частей, способных решить одну и ту же проблему. Обработка одной проблемы занимает целую минуту. Если один из обработчиков занят, запрос переходит прямо к следующему (пропускает полностью занятый обработчик).

Итак, мой вопрос: как отправить несколько запросов один за другим?

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Как уже говорил Майкл, ваша специальная реализация COR ( Цепочка ответственности ).

Если вашим требованием является просто асинхронный многопоточный код , то COR не является подходящим шаблоном для использования. Вместо этого используйте Customized Singleton с возможностью предоставления следующего доступного экземпляра из пула 'n' экземпляров.

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

Если мы видим структуру шаблона COR, он содержит цепочку, образованную ссылками типа Обработчик с методом handleRequest () . Каждый конкретный обработчик специализируется на обработке одного типа запроса , реализуя handleRequest (), что-то вроде следующего

if (canHandle){
    handleIt();
} else if (hasNextHandler()){
    passItToNextHandler();
} else {
    // complete chain is unable to handle it. So leave it may be log it
}

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

Я бы предпочел поддерживать чистоту COR, связывая один экземпляр каждого типа конкретного обработчика в цепочке. Обработчик, в котором вам нужно асинхронно использовать несколько экземпляров, делегирует эту многопоточную задачу объектному пулу из handleRequest (). Может быть настроенным синглтоном, который обрабатывает «n» экземпляров вместо одного.

Это разделит две проблемы, а именно COR и Object pooling. Оба могут поддерживаться независимо друг от друга без необходимости какого-либо взлома.

0 голосов
/ 05 ноября 2019

Во-первых, это специализированная реализация цепи ответственности. Не думайте, что все цепи ответственности делают подобные вещи, потому что они этого не делают.

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

Вот быстрый набросок кода

interface Link {
    void handle(int i);
}

class SlowLink implements Link {
    private final AtomicBoolean isBusy = new AtomicBoolean(false);
    private final Link next;

    SlowLink(Link next) { this.next = next; }

    @Override
    public void handle(int i) {
        if (isBusy.compareAndSet(false, true)) {
            new Thread(() -> handleAsync(i)).start();
        }
        else {
            next.handle(i);
        }
    }

    private void handleAsync(int i) {
        try {
            Thread.sleep(3000);
            System.out.println("slow " + i);
            isBusy.set(false);
        }
        catch (InterruptedException e) {}
    }
}

class QuickLink implements Link {
    @Override
    public void handle(int i) {
        System.out.println("quick " + i);
    }
}

class Scratch {
    public static void main(String[] args) throws InterruptedException {
        Link chain = new SlowLink(new QuickLink());
        chain.handle(5);
        Thread.sleep(1000);
        chain.handle(2);
    }
}
...