0

我在浏览一本 JMS 书籍时遇到了一个问题。下面是代码。我的问题与线程有关,因此我删除了不必要的 JMS 代码。

public class MessageConsumer implements MessageListener{

public MessageConsumer(){   //Constructor
   //configure JMS Connections
}

@Override
public void onMessage(Message message) {
    //receive message
}

public static void main(String[] args) {
    new Thread(){
        @Override
        public void run() {
            new MessageConsumer();
        }
    }.start();  
  }
}

在上面的代码中为什么作者将构造函数作为一个新线程来调用。我尝试如下调用构造函数,它给出了相同的结果

public static void main(String[] args) {
    new MessageConsumer();  
}

那么以上两种方式有什么区别。我知道创建一个新的 Thread() 将创建一个单独的新线程。但是,在这个 JMS 的简单示例中,我是否需要将构造函数作为单独的线程调用?

4

1 回答 1

0

这是一种称为“泄漏 this-pointer”的线程反模式,不应使用。

当然,我假设(因为您剥离了 JMS 代码)构造函数正在建立与 JMS 的连接,以便在onMessage()回调中接收消息。这将涉及将this指针暴露给 JMS,以便它知道将传入消息发布到哪个回调。

底线是: 的实例 ( this)MessageConsumer没有准备好暴露在类之外。

我怀疑作者的意图是为 JMS 生成一个新线程,以便主线程可以继续做其他事情,否则程序不会做很多其他事情。但是由于反模式,它不应该被使用。

这是另一种模式:

 public class MessageConsumer implements MessageListener {

    final JmsConnectionInfo connInfo; // or something.
    public MessageConsumer(JmsConnectionInfo connInfo) {
       this.connInfo = connInfo;
    }

    public void setupConnection() {
       // Do JMS stuff here. In this method you can expose 
       // the 'this' pointer to JMS without problem.
    }

    @Override
    public void onMessage (Message message) {
       // Receive message here.
    }
 }

这样,您可以MessageConsumer在任何您喜欢的线程中自由创建一个,但启动 JMS 连接将涉及对setupConnection().

this永远不要从构造函数中暴露指针。

于 2015-09-16T08:46:21.973 回答