много производителей и один потребитель опрашивают все сообщения одновременно - PullRequest
2 голосов
/ 01 февраля 2012

У меня есть веб-приложение, которое для каждого запроса сохраняет некоторую информацию (например, IP-адрес клиента) в некоторой коллекции. Время от времени мне нужно очищать его, сериализовать все элементы в XML и отправлять XML в другой веб-сервис. Я мог бы создать и отправить один xml для каждого запроса, но я бы предпочел отправлять данные порциями (не слишком часто связываться с веб-сервисом). У меня нет требований относительно максимального размера коллекции (за исключением отсутствия ошибки outofmemoryerror), периода, когда файл должен быть отправлен, и размера файла min / max. Также допустимо, что иногда происходит сбой jvm, и мы теряем все данные, хранящиеся в памяти.

Я понимаю, что многие потоки (потоки, генерируемые контейнером сервлета) будут добавлять элементы в коллекцию, и время от времени один потребительский поток будет извлекать все элементы из коллекции, сериализовать их в xml и отправлять файл. Не могли бы вы порекомендовать дизайн?

Должен ли я использовать занятое ожидание в потоке потребителя? Какой поток (производитель или потребитель) должен проверить, равен ли размер коллекции максимальному / пороговому размеру? Могу ли я использовать синхронизацию в коллекции и notifyAll на стороне производителя для уведомления потребителя? Должен ли я использовать синхронизацию и while (size (collection);

Это моя первая мысль. Я уверен, что есть много причин для критики:

public void add(Info info){
    synchronized (collection) {
        collection.add(info);
        if (collection.size() > THRESHOLD) {
             collection.notify();
        }
    }
}

public void send(){
    while (true) {
        List<Info> temp = null;
        synchronized (collection) {
            try {
                collection.wait();
            } catch (InterruptedException e) {
            }
            List<Info> temp = new ArrayList<>(collection);
            collection.clear();
        }
        serializeAndSend(temp);
    }

}

1 Ответ

2 голосов
/ 01 февраля 2012

Вместо того, чтобы кататься по своему усмотрению, хотя бы подумайте о том, чтобы использовать что-то вроде LinkedBlockingQueue или что-то еще из java.util.concurrent.

Как есть, ваш текущийКод не будет работать, поскольку ваши вызовы notify() и wait() не работают с одним и тем же объектом.

Ваши требования интересны.Что, если JVM умрет (по любой причине), и вы потеряете все данные из очереди, например?В любом случае, следуя вашему комментарию - вы все равно можете сделать что-то похожее на то, что вы делали раньше - отфильтровать все операции добавления с помощью пользовательского метода, и если коллекция достигнет определенного размера, то serializeAndSend.Однако, если вы будете следовать этому подходу, вам не понадобится коллекция с поддержкой параллелизма.Я также вижу, что вы обновили свой код для вызова collection.wait(), что хорошо.

...