2009-09-18 11 views
5

私は同時に、この方法XMPPConnection.sendPacket( パケット)を呼び出すことができるだということを確認するために、余分な目をしたい同時スレッドからXMPPConnection.sendPacketを呼び出すことはできますか?

動機。私の現在のコードでは、Callableのリスト(最大3)を連続して呼び出しています。各Callableは、1つのXMPPConnection上でXMPPパケットを送受信します。 &各Callableは共有XMPPConnection上でsendPacketを同期せずに呼び出します。

XMPPConnection

class XMPPConnection 
{ 
    private boolean connected = false; 

    public boolean isConnected() 
    { 
     return connected; 
    } 

    PacketWriter packetWriter; 

    public void sendPacket(Packet packet) 
    { 
     if (!isConnected()) 
      throw new IllegalStateException("Not connected to server."); 

     if (packet == null) 
      throw new NullPointerException("Packet is null."); 

     packetWriter.sendPacket(packet); 
    } 
} 

PacketWriter

class PacketWriter 
{ 
    public void sendPacket(Packet packet) 
    { 
     if (!done) { 
      // Invoke interceptors for the new packet 
      // that is about to be sent. Interceptors 
      // may modify the content of the packet. 
      processInterceptors(packet); 

      try { 
       queue.put(packet); 
      } 
      catch (InterruptedException ie) { 
       ie.printStackTrace(); 
       return; 
      } 
      synchronized (queue) { 
       queue.notifyAll(); 
      } 

      // Process packet writer listeners. Note that we're 
      // using the sending thread so it's expected that 
      // listeners are fast. 
      processListeners(packet); 
    } 

    protected PacketWriter(XMPPConnection connection) 
    { 
     this.queue = new ArrayBlockingQueue<Packet>(500, true); 
     this.connection = connection; 
     init(); 
    } 
} 

私は結論は何

PacketWriterはBlockingQueueのを使用しているので、呼び出すための私の意図しても問題はありませんセ複数のスレッドからのndPacket。私は正しいですか?

答えて

0

ここで十分な情報を提供していません。

我々は、次が実装されているのか分からない:

  • processInterceptors
  • processListeners
  • /'は行わ' 変数を読み書き

?あるスレッドがそれをtrueに設定すると、他のすべてのスレッドは自動的に失敗します。

これはスレッドセーフではありませんが、投稿した内容から確実にわかる方法はありません。

その他の問題:

  • なぜPacketWriterはそれが唯一の方法で使用されますXMPPConnectionwhenのクラスのメンバである

  • なぜPacketWriterにはXMPPConnectionのメンバーvarがあり、それを使用していないのですか?
0

Java 5+に制限できる場合は、BlockingQueueの使用を検討することもできます。 Java APIのドキュメントから

、ArrayBlockingQueue使用するためのマイナーチェンジで:あなたの使用方法については

class Producer implements Runnable { 
    private final BlockingQueue queue; 
    Producer(BlockingQueue q) { queue = q; } 
    public void run() { 
    try { 
     while(true) { queue.put(produce()); } 
    } catch (InterruptedException ex) { ... handle ...} 
    } 
    Object produce() { ... } 
} 

class Consumer implements Runnable { 
    private final BlockingQueue queue; 
    Consumer(BlockingQueue q) { queue = q; } 
    public void run() { 
    try { 
     while(true) { consume(queue.take()); } 
    } catch (InterruptedException ex) { ... handle ...} 
    } 
    void consume(Object x) { ... } 
} 

class Setup { 
    void main() { 
    BlockingQueue q = new ArrayBlockingQueue(); 
    Producer p = new Producer(q); 
    Consumer c1 = new Consumer(q); 
    Consumer c2 = new Consumer(q); 
    new Thread(p).start(); 
    new Thread(c1).start(); 
    new Thread(c2).start(); 
    } 
} 

を、あなたはあなたの本当の送信者(実際の接続の所有者は)消費者もあるだろうし、パケットの作成者/送信者はプロデューサです。

その他の待機パケットの前に送信されるフラッシュオーバーライドXMPPパケットを許可するために、PriorityBlockingQueueを使用することができます。

また、デザイン上のGlenのポイントも良い点です。独自のAPIを作成するのではなく、Smack API(http://www.igniterealtime.org/projects/smack/)を参照してください。

2

はい、別のスレッドからパケットを問題なく送信できます。

Smackブロッキングキューは、異なるスレッドが同時に出力ストリームを書き込むことができないためです。 Smackは、出力ストリームをパケット単位で書き込むことによって、同期させる責任があります。

Smackによって実装されるパターンは、単に典型的なプロデューサ/コンシューマ並行パターンです。いくつかのプロデューサ(スレッド)と1つのコンシューマ(独自のスレッドで動作するSmackのPacketWriter)を持つことができます。

よろしくお願いいたします。

関連する問題