Java 防止消息处理的竞争条件
我有一个J2EE应用程序,它通过web服务接收消息(事件)。消息的类型不同(根据类型需要不同的处理),并按特定顺序发送。它发现了一个问题,即某些消息类型比其他消息类型需要更长的处理时间。结果是,序列中第二个接收到的消息可以在序列中第一个消息之前处理。我试图通过在处理消息的方法周围放置一个同步块来解决这个问题。这似乎有效,但我不相信这是“正确”的方法?是否有更合适的替代方案,或者这是“可接受的”?我加入了一小段代码,试图更清楚地解释。。。。任何建议/指导都将不胜感激Java 防止消息处理的竞争条件,java,jakarta-ee,Java,Jakarta Ee,我有一个J2EE应用程序,它通过web服务接收消息(事件)。消息的类型不同(根据类型需要不同的处理),并按特定顺序发送。它发现了一个问题,即某些消息类型比其他消息类型需要更长的处理时间。结果是,序列中第二个接收到的消息可以在序列中第一个消息之前处理。我试图通过在处理消息的方法周围放置一个同步块来解决这个问题。这似乎有效,但我不相信这是“正确”的方法?是否有更合适的替代方案,或者这是“可接受的”?我加入了一小段代码,试图更清楚地解释。。。。任何建议/指导都将不胜感激 public class Ev
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;
}
public类eventserviceinpl实现EventService{
公共字符串提交(字符串消息){
如果(msg==null)
回报(“NAK”);
EventQueue.getInstance().submit(msg);
返回“确认”;
}
}
公共类事件队列{
私有静态EventQueue实例=null;
私有静态int队列长度=10000;
保护布尔完成=假;
BlockingQueue myQueue=新链接的BlockingQueue(队列长度);
受保护的事件队列(){
新线程(新使用者(myQueue)).start();
}
公共静态事件队列getInstance(){
if(实例==null){
instance=neweventqueue();
}
返回实例;
}
公共作废提交(字符串事件){
试一试{
myQueue.put(事件);
}捕获(中断异常例外){
}
}
类使用者实现Runnable{
受保护的阻塞队列;
消费者(阻止队列队列){this.queue=theQueue;}
公开募捐{
试一试{
while(true){
Object obj=queue.take();
过程(obj);
如果(完成){
返回;
}
}
}捕获(中断异常例外){
}
}
作废处理(对象obj){
事件=新事件((字符串)obj);
EventHandler=EventHandlerFactory.getInstance(事件);
handler.execute();
}
}
//优雅地排队
公众假期结束(){
this.done=true;
}
如果事件要按特定顺序处理,那么为什么不尝试将“eventID”和“orderID”字段添加到消息中?这样,EventServiceImpl类就可以按正确的顺序进行排序、排序和执行(无论创建和/或传递给处理程序的顺序如何)
同步handler.execute()
块将不会得到期望的结果,我预计。synchronized
关键字所做的只是防止多个线程同时执行该块。它在正确排序下一个线程方面没有任何作用
如果synchronized
块确实能让事情顺利进行,那么我断言您是非常幸运的,因为消息是按照正确的顺序创建、传递和执行的。在多线程环境中,这是不确定的!我会采取措施确保您能够控制它,而不是依靠运气
例如:
这样做可以确保正确的处理并促进多线程的良好使用。我不确定您正在使用的框架(EJB(MDB)/JMS)是什么。通常应该避免在EJB/JMS这样的托管环境中使用同步(这不是一个好的实践)。一种解决方法是
- 客户端应该等待服务器的确认,然后再发送下一条消息
- 这样,客户机本身就可以控制事件的顺序
在这种情况下,我对发送消息的系统没有任何访问/控制权,尽管每条消息都包含一个序列号。我使用cxf构建了接收消息的web服务。您有多个客户端以其自己的消息序列发送消息?该服务只有一个客户端。实际上