许多生产者和一个消费者一次轮询所有消息

时间:2012-02-01 02:22:43

标签: java multithreading message-queue

我有一个webapp,每个请求都会在某些集合中存储一些信息(例如客户端IP地址)。我不时需要清空它,将所有元素序列化为xml并将xml发送到其他Web服务。我可以为每个请求创建并发送一个xml,但我宁愿以块的形式发送数据(不要经常与webservice通信)。我没有关于集合的最大大小的要求(除了没有outofmemoryerror),必须发送文件的时间段和最小/最大文件大小。有时jvm崩溃并且我们丢失了存储在内存中的所有数据也是可以接受的。

据我所知,许多线程(servlet容器生成的线程)将向集合添加元素,偶尔一个消费者线程将从集合中获取所有元素,将它们序列化为xml并发送文件。你能推荐一下这个设计吗?

我应该在消费者线程中使用忙等待吗? 哪个线程(生产者或消费者)应检查集合大小是否为某个最大/阈值大小? 我可以在集合上使用synchronize并在生产者端使用notifyAll来通知消费者吗? 我应该在消费者端使用synchronize和while(size< MAX){wait()}吗? 排水要比List temp = new ArrayList<>(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 个答案:

答案 0 :(得分:2)

至少考虑使用LinkedBlockingQueuejava.util.concurrent中的其他内容,而不是自己动手。

按原样,您当前的代码无法使用,因为notify()wait()调用无法针对同一对象进行操作。

您的要求很有趣。例如,如果JVM死亡(出于任何原因),并且您丢失了所有排队的数据,该怎么办?无论如何,按照您的评论 - 您仍然可以执行类似于之前的操作 - 通过自定义方法过滤所有添加操作,如果集合达到特定大小,则serializeAndSend。但是,如果您遵循这种方法,那么您真的不需要具有并发支持的集合。我还看到您更新了代码以致电collection.wait(),这很好。