2009-09-18 11 views
5

MotywacjaCzy mogę wywołać XMPPConnection.sendPacket z równoczesnych wątków?

Chcę dodatkowe oczy, aby potwierdzić, że jestem w stanie wywołać tę metodę XMPPConnection.sendPacket ( Packet) jednocześnie. Dla mojego obecnego kodu, przywołuję Listę kalendarzy (maks. 3) w sposób seryjny. Każdy Callable wysyła/odbiera pakiety XMPP na jednym kawałku XMPPConnection. Planuję zrównoleglować te Callables poprzez wyrzucenie wielu wątków. & Każdy Callable będzie wywoływał sendPacket na wspólnym XMPPConnection bez synchronizacji.

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

Co Kończę

Ponieważ PacketWriter stosuje BlockingQueue, nie ma żadnego problemu z moim zamiarem powołania se ndPacket z wielu wątków. Mam rację ?

Odpowiedz

0

Nie podałeś wystarczających informacji tutaj.

Nie wiemy, w jaki sposób realizowane są następujące:

  • processInterceptors
  • processListeners

Kto czyta/zapisuje zmienną 'Gotowe'? Jeśli jeden wątek ustawi go na wartość true, wszystkie pozostałe wątki będą po cichu zawieść.

Już na pierwszy rzut oka nie wygląda to na wątek bezpieczny, ale na podstawie tego, co napisałeś, nie można jednoznacznie stwierdzić.

Inne kwestie:

  • Dlaczego PacketWriter członkiem klasy XMPPConnectionwhen jest używany tylko w jednej metodzie?
  • Dlaczego pakiet PacketWriter ma zmienną XMPPConnection, a nie używa jej?
0

Możesz rozważyć użycie BlockingQueue, jeśli możesz ograniczyć do Java 5+.

Od docs Java API, z niewielką zmianą w użyciu 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(); 
    } 
} 

za korzystanie chcesz mieć prawdziwego nadawcę (posiadacz rzeczywistego połączenia) będzie konsumentów oraz sporządzających pakiet/nadawcami są producenci.

Ciekawą dodatkową myślą jest to, że możesz użyć PriorityBlockingQueue, aby zezwolić na flashowanie pakietów XMPP, które są wysyłane przed innymi oczekującymi pakietami.

Również punkty Glen's dotyczące projektu są dobre.Możesz raczej spojrzeć na Smack API (http://www.igniterealtime.org/projects/smack/) zamiast tworzyć własne.

2

Tak, możesz bezproblemowo wysyłać pakiety z różnych wątków.

Kolejka blokowania Smack jest, ponieważ nie można pozwolić, aby różne wątki zapisywały strumień wyjściowy w tym samym czasie. Smack bierze odpowiedzialność za synchronizację strumienia wyjściowego, pisząc go z podziałem na pakiety.

Wzór wdrożony przez Smacka jest po prostu typowym wzorem współbieżności producent/konsument. Możesz mieć kilku producentów (twoje wątki) i tylko jednego konsumenta (Smack's PacketWriter działa w swoim wątku).

Pozdrawiam.