簡體   English   中英

將JMS與多線程客戶端一起使用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM