2012-02-01 43 views
2

我有一个web应用程序,为每个请求存储一些信息(例如客户端ip地址)在一些集合中。有时我需要将它清空,将所有元素序列化为xml并将xml发送到其他Web服务。我可以为每个请求创建和发送一个xml,但我宁愿发送数据块(不要与web服务过于频繁地通信)。我对集合的最大大小没有要求(除了没有超出内存的错误),必须发送文件的时间以及最小/最大文件大小。有时候jvm崩溃并且我们丢失了存储在内存中的所有数据也是可以接受的。许多生产者和一个消费者一次轮询所有消息

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

我应该在消费者线程中使用busy-wait吗? 哪个线程(生产者或消费者)应该检查集合大小是否是某个最大/阈值大小? 我可以使用同步集合和生产者端的notifyAll来通知消费者? 我应该在客户端使用同步和while(大小< MAX){wait()}吗? 将drainTo比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); 
    } 

}

回答

2

不是滚动自己的,至少可以考虑使用类似LinkedBlockingQueuejava.util.concurrent别的东西。

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

您的需求很有趣。例如,如果JVM死亡(出于任何原因),并且您丢失了所有排队的数据?无论如何,你的评论 - 你仍然可以做类似于你以前的事情 - 通过自定义方法过滤所有添加操作,并且如果集合达到一定的大小,那么serializeAndSend。但是,如果遵循这种方法,那么您确实不需要具有并发支持的集合。我还看到你更新了你的代码来拨打collection.wait(),这很好。

+0

谢谢,但LinkedBlockingQueue会改变这种情况下的任何事情(只有在预计特定阈值大小时才应该调用take/drainTo)? – user1051075 2012-02-01 12:03:34

+0

@ user1051075 - 请参阅我的答案更新。 (放在那里,而不是评论,给定长度。) – ziesemer 2012-02-01 13:40:33

相关问题