Цепочка ответственности - обработка более одного запроса

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

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

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

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


person Gonper    schedule 04.11.2019    source источник
comment
При чем тут реализация? Потому что обычно веб-сервер позаботится об этом за вас (каждый запрос обслуживается отдельным потоком).   -  person Arlo Guthrie    schedule 04.11.2019
comment
Он никак не связан с веб-сервером.   -  person Gonper    schedule 04.11.2019


Ответы (2)


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

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

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

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);
    }
}
person Michael    schedule 04.11.2019

Как упомянул Майкл, у вас есть специальная реализация COR (Chain of Responsibility).

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

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

Если мы видим структуру паттерна COR, то она содержит цепочку, образованную связями типа Handler с методом 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 и объединение объектов. Оба могут поддерживаться независимо без какого-либо взлома.

person Kedar Tokekar    schedule 06.11.2019