在阅读了JMS的一些文档之后,我对synchronous
和asynchronouns
一词感到困惑。
请参阅此页:http://docs.oracle.com/cd/E19798-01/821-1841/bncdq/index.html
同步
您使用receive方法同步使用消息。 您可以在调用start方法后随时使用此方法:
connection.start(); Message m = consumer.receive(); connection.start(); Message m = consumer.receive(1000); // time out after a second
要异步使用消息,请使用消息侦听器,如下一节所述。
异步
JMS消息监听器 消息侦听器是一个对象,充当消息的异步事件处理程序。此对象实现MessageListener接口,该接口包含一个onMessage方法。在onMessage方法中,您可以定义消息到达时要采取的操作。
使用setMessageListener方法向特定MessageConsumer注册消息侦听器。例如,如果您定义一个名为Listener的类来实现MessageListener接口,则可以按如下方式注册消息监听器:
Listener myListener = new Listener(); consumer.setMessageListener(myListener);
我有两个问题:
据我所知,JMS的本质是异步的。生产者将消息发布到队列/主题,它不需要等待消费者。这是异步行为。怎么会“同步”?
如果“mesageListener”是异步的,但在我使用spring-jms的测试中,我发现它总是在一个线程中运行。这意味着,如果我在Thread.sleep(2000)
中写onMessage
,则必须等待2秒才能处理下一条消息。是“异步”吗?
答案 0 :(得分:17)
如果您更好地理解这一点,consumer.receive()
使用 pull 模型:您从队列中读取并被阻止等待此消息,直到它出现,或者已经过了一些超时。
使用侦听器使用 push 模型:您注册一个侦听器,并在收到消息时,在一个单独的线程中调用侦听器。
一切都在Java中的线程中完成,并且侦听器调用也不例外。侦听器消息处理是否阻止处理队列中的其他消息取决于专用于消息处理的线程数。如果将Spring配置为使用5个线程池来异步处理消息,那么5个侦听器将能够并行处理消息。
答案 1 :(得分:8)
就像我理解这一点:
asynchronous - MessageListener:在侦听队列的服务器上使用它。当消息到达时,立即处理它。服务器一直在监听这个队列。
synchronous - consumer.receive(1000):在客户端应用程序上使用此功能,现在需要检查是否有针对此客户端的消息。示例:每60秒轮询一次。这只会很快打开与服务器的连接。 1000毫秒将保持此连接打开。如果消息在这1000毫秒内到达,则消息将被消耗并且连接已关闭。
答案 2 :(得分:3)
您正在端到端地看待它:从发布者到消费者。是的,它是从发布者到消费者的异步传递,而不管Sync / Async使用者。但问题中的同步/异步仅供消费者使用,即从JMS代理(例如:ApacheMQ)到消费者。正如其他人所指出的,Sync消费者从代理顺序地提取消息并等待消息。异步使用者注册一个回调消息(onMessage)。当这些消息从JMS代理异步传递给它们时,异步使用者可以继续做其他事情。
答案 3 :(得分:0)
我对同步/异步的理解不同。
同步:主叫方(发送方)必须等待,直到收到消费者的响应为止(直到超时)-请求/回复模式
异步:主叫方(发件人)仅发布消息并继续其工作,而消费者在消息到达后即进行处理(一种方式请求)
任何MOM(Message Oriented Middle ware)都遵循促进异步通信的服务激活器模式。我的一个项目已经实现了一个围绕JMS的框架,以使通信真正实现同步。
这是使基于MOM的通信像同步一样起作用的方法之一。您可能会发现其他实现方式,例如request-reply mechanism。