0

JMS の本を読んでいるときに、1 つの質問に出くわしました。以下はコードです。私の質問はスレッドに関するものなので、不要な 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();  
}

上記の2つの方法に違いはありますか。新しい Thread() を作成すると、別の新しいスレッドが作成されることはわかっています。ただし、JMS のこの単純な例では、コンストラクターを別のスレッドとして呼び出す必要がありますか?

4

1 に答える 1

0

これは「The Leaking this-pointer」と呼ばれるスレッドのアンチパターンであり、使用すべきではありません。

onMessage()確かに、コールバックでメッセージを受信するために、コンストラクターが JMS への接続を設定していると想定しています (JMS コードを削除したため) 。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 に答える