java阻止消息处理的竞争条件
我有一个J2EE应用程序,它通过web服务接收消息(事件)。消息的类型不同(根据类型需要不同的处理),并按特定顺序发送。它发现了一个问题,即某些消息类型比其他消息类型需要更长的处理时间。结果是,序列中第二个接收到的消息可以在序列中第一个消息之前处理。我试图通过在处理消息的方法周围放置一个同步块来解决这个问题。这似乎有效,但我不相信这是“正确”的方法?是否有更合适的替代方案,或者这是“可接受的”?我加入了一小段代码,试图更清楚地解释。。。。任何建议/指导都将不胜感激
public class EventServiceImpl implements EventService {
public String submit (String msg) {
if (msg == null)
return ("NAK");
EventQueue.getInstance().submit(msg);
return "ACK";
}
}
public class EventQueue {
private static EventQueue instance = null;
private static int QUEUE_LENGTH = 10000;
protected boolean done = false;
BlockingQueue<String> myQueue = new LinkedBlockingQueue<String>(QUEUE_LENGTH);
protected EventQueue() {
new Thread(new Consumer(myQueue)).start();
}
public static EventQueue getInstance() {
if(instance == null) {
instance = new EventQueue();
}
return instance;
}
public void submit(String event) {
try {
myQueue.put(event);
} catch (InterruptedException ex) {
}
}
class Consumer implements Runnable {
protected BlockingQueue<String> queue;
Consumer(BlockingQueue<String> theQueue) { this.queue = theQueue; }
public void run() {
try {
while (true) {
Object obj = queue.take();
process(obj);
if (done) {
return;
}
}
} catch (InterruptedException ex) {
}
}
void process(Object obj) {
Event event = new Event( (String) obj);
EventHandler handler = EventHandlerFactory.getInstance(event);
handler.execute();
}
}
// Close queue gracefully
public void close() {
this.done = true;
}
# 1 楼答案
我不确定您使用的框架(EJB(MDB)/JMS)是什么。通常应该避免在托管环境中使用像EJB/JMS那样的同步(这不是一个好的实践)。一种方法是
请注意,如果有多个客户端提交消息,这将不起作用
编辑:
在这种情况下,web服务的客户端按顺序发送消息,而不考虑消息处理时间。它只是一个接一个地转储消息。这是基于Queue ( First In First Out )的解决方案的一个很好的例子。我建议以下两种方法来实现这一点
使用JMS。这将增加添加JMS providers和编写一些管道代码的额外开销
使用一些多标题模式,如Producer-Consumer,其中web服务处理程序将在队列中转储传入消息,单线程使用者将一次消费一条消息。请参阅this example使用java。util。并发包
使用数据库。将传入消息转储到数据库中。使用不同的基于调度器的程序扫描数据库(基于序列号),并相应地处理消息
对于这类问题,第一和第三种解决方案是非常标准的。第二种方法很快,不需要在代码中添加任何库
# 2 楼答案
如果事件是按特定顺序处理的,那么为什么不尝试向消息中添加“eventID”和“orderID”字段呢?通过这种方式,EventServiceImpl类可以按照正确的顺序进行排序、排序和执行(无论它们是以何种顺序创建和/或交付给处理程序的)
我预计,同步
handler.execute()
块不会得到期望的结果。synchronized
关键字所做的就是防止多个线程同时执行该块。它在正确排序下一个线程方面没有任何作用如果
synchronized
块确实能让事情顺利进行,那么我断言您非常幸运,因为消息是按照正确的顺序创建、传递和执行的。在多线程环境中,这是不能保证的!我会采取措施确保你能控制这一切,而不是依赖好运例如:
沿着这些思路,可以确保正确的处理,并促进多线程的良好使用