2009-09-18 13 views
5

motivazionePosso richiamare XMPPConnection.sendPacket da thread simultanei?

voglio occhi in più per confermare che sono in grado di chiamare questo metodo XMPPConnection.sendPacket ( Packet) contemporaneamente. Per il mio codice attuale, sto invocando una lista di Callables (max 3) in modo seriale. Ogni Callable invia/riceve pacchetti XMPP su un pezzo di XMPPConnection. Ho intenzione di parallelizzare questi Callables ruotando più thread & ogni Callable invocherà sendPacket sul XMPPConnection condiviso senza sincronizzazione.

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(); 
    } 
} 

Cosa concludo

Dal momento che la PacketWriter sta usando una BlockingQueue, non c'è nessun problema con la mia intenzione di invocare SE ndPacket da più thread. Ho ragione ?

risposta

0

Non hai fornito abbastanza informazioni qui.

Non sappiamo come il seguente sono implementate:

  • processInterceptors
  • processListeners

Chi legge/scrive la variabile 'fatto'? Se un thread lo imposta su true, allora tutti gli altri thread falliranno in modo silenzioso.

Da una rapida occhiata, questo non sembra thread sicuro, ma non c'è modo di dire con certezza da quello che hai postato.

Altre questioni:

  • Perché PacketWriter un membro della classe di XMPPConnectionwhen è usato solo in un metodo?
  • Perché PacketWriter ha un var di membro XMPPConnection e non lo usa?
0

Si può prendere in considerazione l'utilizzo di un BlockingQueue se è possibile limitare a Java 5+.

Dalla documentazione API di Java, con una piccola modifica per utilizzare 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(); 
    } 
} 

per il vostro uso avresti il ​​tuo vero mittente (titolare della connessione effettiva) essere il consumatore, e gli estensori dei pacchetti/i mittenti sono i produttori.

Un altro aspetto interessante è che è possibile utilizzare PriorityBlockingQueue per consentire l'override dei pacchetti XMPP flash inviati prima di qualsiasi altro pacchetto in attesa.

Inoltre, i punti di Glen sul design sono buoni punti.Potresti dare un'occhiata all'API Smack (http://www.igniterealtime.org/projects/smack/) piuttosto che crearne una tua.

2

Sì, è possibile inviare pacchetti da thread diversi senza problemi.

La coda di blocco Smack è perché ciò che non si può fare è lasciare che i diversi thread scrivano il flusso di output allo stesso tempo. Smack si assume la responsabilità di sincronizzare il flusso di output scrivendolo con una granularità per pacchetto.

Il modello implementato da Smack è semplicemente un tipico modello di concorrenza produttore/consumatore. Potresti avere diversi produttori (i tuoi thread) e un solo consumatore (il PacketWriter di Smack in esecuzione nella propria thread).

Saluti.

Problemi correlati