gpt4 book ai didi

java - 防止消息处理的竞争条件

转载 作者:行者123 更新时间:2023-11-30 05:55:56 26 4
gpt4 key购买 nike

我有一个 J2EE 应用程序,它通过 Web 服务接收消息(事件)。消息具有不同的类型(根据类型需要不同的处理)并按特定顺序发送。它发现了一个问题,即某些消息类型的处理时间比其他消息类型长。结果是序列中第二个收到的消息可能会在序列中的第一个之前被处理。我试图通过在处理消息的方法周围放置一个同步块(synchronized block)来解决这个问题。这似乎可行,但我不确定这是“正确”的方法吗?是否有可能更合适的替代方案或者这是“可接受的”?我已经包含了一小段代码来尝试更清楚地解释。 ....任何建议/指导表示赞赏。

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;
}

最佳答案

我不确定您使用的框架 (EJB(MDB)/JMS) 是什么。通常应避免在像 EJB/JMS 这样的 Managed Environment 中使用同步(这不是一个好习惯)。一种绕过的方法是

  • 客户端在发送下一条消息之前应该等待服务器的确认。
  • 这样您的客户自己将控制事件的顺序。

请注意,如果有多个客户端提交消息,这将不起作用。

编辑:

您遇到这样一种情况,即 Web 服务的客户端在不考虑消息处理时间的情况下按顺序发送消息。它只是一个接一个地转储消息。这是一个很好的案例 Queue ( First In First Out )基于解决方案。我建议通过以下两种方式来实现这一点

  1. 使用 JMS .这将有额外的开销来添加 JMS providers并编写一些管道代码。

  2. 使用一些多主题模式,例如 Producer-Consumer其中,您的 Web 服务处理程序会将传入的消息转储到队列中,而单线程 消费者将一次使用一条消息。参见 this example使用 java.util.concurrent 包。

  3. 使用数据库。将传入的消息转储到数据库中。使用不同的基于调度程序的程序来扫描数据库(基于序列号)并相应地处理消息。

    第一种和第三种解决方案对于这类问题来说是非常标准的。第二种方法会很快,并且不需要在您的代码中添加任何额外的库。

关于java - 防止消息处理的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7647431/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com