【问题标题】:many producers and one consumer polling all messages at once许多生产者和一个消费者同时轮询所有消息
【发布时间】:2012-02-23 18:47:32
【问题描述】:

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

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

我应该在消费者线程中使用忙等待吗? 哪个线程(生产者或消费者)应该检查集合大小是否是某个最大/阈值大小? 我可以在集合上使用同步并在生产者端使用 notifyAll 来通知消费者吗? 我应该在消费者端使用 synchronize 和 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);
    }

}

【问题讨论】:

    标签: java multithreading message-queue


    【解决方案1】:

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

    按原样,您当前的代码将不起作用,因为您的 notify()wait() 调用未针对同一个对象工作。

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

    【讨论】:

    • 谢谢,但是在这种情况下 LinkedBlockingQueue 会改变什么吗(take/drainTo 应该只在需要特定阈值大小时调用)?
    • @user1051075 - 请查看我的答案的更新。 (放在那里而不是评论,给定长度。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 2015-03-27
    • 1970-01-01
    相关资源
    最近更新 更多