[英]Consuming JMS with a multi-threaded client
我正在嘗試使用多個線程來消耗jms隊列。 我知道每個線程應該有一個單獨的JMS會話,並且我在代碼中所做的工作如下所示。 但是我得到一個奇怪的例外
這是異常堆棧跟蹤:
javax.jms.IllegalStateException: Forbidden call on a closed connection.
at org.objectweb.joram.client.jms.Connection.checkClosed(Connection.java:404)
at org.objectweb.joram.client.jms.Connection.createSession(Connection.java:530)
at MessageWorker.run(ReceiveJmsDemoMultiThreaded.java:96)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
我需要您的幫助,因為這對我來說是個難題
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class ReceiveJmsDemoMultiThreaded {
public static void main(String[] args) {
Context context = null;
ConnectionFactory factory = null;
Connection connection = null;
Destination destination = null;
try {
context = getInitialContext();
factory = (QueueConnectionFactory) context.lookup("JQCF");
destination = (Destination) context.lookup("sampleQueue");
connection = factory.createConnection();
final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(new MessageWorker(connection, destination) );
executor.submit(new MessageWorker(connection, destination) );
executor.submit(new MessageWorker(connection, destination) );
executor.submit(new MessageWorker(connection, destination) );
connection.start();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (context != null) {
try {
context.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
private static InitialContext getInitialContext() throws NamingException {
Properties prop = new Properties();
prop.put("java.naming.provider.url", "rmi://localhost:1099");
prop.put("java.naming.factory.initial",
"org.objectweb.carol.jndi.spi.MultiOrbInitialContextFactory");
return new InitialContext(prop);
}
}
class MessageWorker extends Thread {
Connection connection = null;
Destination dest = null;
Session session = null;
Destination destination = null;
public MessageWorker(Connection connection, Destination dest) {
this.connection = connection;
this.destination = dest;
}
@Override
public void run() {
try {
MessageConsumer receiver = null;
System.out.println("Starting Thread "+currentThread().getName());
while (true) {
try {
System.out.println("Waiting for next msg "+currentThread().getName());
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
receiver = session.createConsumer(destination);
Message msg = receiver.receive();
if (msg instanceof Message && msg != null) {
System.out.println("STARTING consuming "+msg.toString()+" by thread "+currentThread().getName() );
Thread.sleep(2000);//some work here
System.out.println("ENDING consuming "+msg.toString()+" by thread "+currentThread().getName() );
}
} catch (JMSException e) {
e.printStackTrace();
System.exit(1);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
非常感謝
您正在看到此問題,因為在主線程中,將作業提交給Executor服務后,使用以下命令關閉了連接:
connection.close();
因此,當線程嘗試使用此共享連接(剛剛關閉)創建Session時,就會收到此異常。 這里沒有什么意外的。 僅出於測試目的,您可以使主線程長時間睡眠,直到所有線程都完成接收消息為止。 這樣,您可以確認您沒有收到此異常。
真正的解決方案可能是關閉Executor服務,並使主線程awaitTermination()
等待提交的作業完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.