在我的JavaEE Web应用程序中,我需要严格按照到达顺序处理传入的消息。我假设我的webapp容器(Tomcat 6)在到达http端口时保留了消息的顺序。
让我头疼的是我在内部处理这些消息的方式。为了改善工作量,我将每条消息的处理附加到ThreadPool,因为这里需要做很多事情,例如XML解析,有时使用外部Web服务丰富数据。处理完成后,我将消息的java表示推送到复杂的流处理引擎esper.codehaus.org,这是线程安全的。这里,检查不同的模式,其中入口顺序是最高要求,例如现象的阈值超过。
我有想法将每个已处理的消息插入到PriorityQueue中,并使用他们在到达时收到的优先级ID(在我的Servlet中,每个消息都会递增)。问题如下:
轮询队列中的元素(最低ID是队列的头部)以将其插入esper的线程可以跳过ID,因为它不会检查缺少的项目。我想插图效果更好:
对于步骤(1)至(4),一切都按预期工作。但是在步骤(5),QueuePoller检索元素6而不是元素4(稍后在步骤(6)插入)。这导致消息顺序:2; 3; 6; 4。
我尝试做的是改变轮询队列头部的实现,以遵循严格的ID顺序。这意味着,如果下一个ID的元素尚未插入队列,则在屏障处等待直到其中。这似乎适用于前10分钟,但后来被绞死,可能是因为一个元素从未插入队列。
过去有过类似问题的人对我有一些暗示吗?
答案 0 :(得分:3)
查看Disruptor - 具有严格顺序的高性能队列(首次输入 - 首次服务)
答案 1 :(得分:1)
您可以立即将传入请求的占位符添加到处理队列中。占位符在后台由线程池预处理,但主处理等待预处理完成。我想到的构造是Future。
答案 2 :(得分:0)
类库提供了灵活的线程池实现以及一些有用的预定义配置。您可以通过调用Executors中的一个静态工厂方法来创建线程池:
根据您的需求,我认为Executors.newSingleThreadExecutor()是最好的。单线程执行程序创建一个工作线程来处理任务,如果它意外死亡则替换它。保证按照任务队列(FIFO,LIFO,优先顺序)强加的顺序依次处理任务。
答案 3 :(得分:0)
正如你的问题所证明的那样,需要一个图表(顺便说一句,+1),优先级队列并不是你想要的好结构。这是因为队列非常乐意为您提供可用的6而不是等待不可用的4。
我认为是时候推出自己的同步容器了。