使用多线程客户端使用JMS

时间:2013-06-05 10:47:47

标签: java multithreading java-ee jms

我正在尝试使用多个线程来使用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 {

    }
}
}

非常感谢

1 个答案:

答案 0 :(得分:2)

您看到此问题是因为在主线程中,在将作业提交到Executor Service之后,使用以下命令关闭连接:

        connection.close();

因此,当线程尝试使用此共享连接(刚刚关闭)创建会话时,它们会收到此异常。这里没什么意外的。 只是为了测试,你可以让你的主线程长时间休眠,直到你的所有线程完成接收消息。这样,您可以确认您没有收到此例外。

真正的解决方案可能是关闭Executor服务并使主线程awaitTermination()等待提交作业的完成。