Java 我可以从并发线程调用XMPPConnection.sendPacket吗?

Java 我可以从并发线程调用XMPPConnection.sendPacket吗?,java,multithreading,concurrency,xmpp,smack,Java,Multithreading,Concurrency,Xmpp,Smack,动机 class XMPPConnection { private boolean connected = false; public boolean isConnected() { return connected; } PacketWriter packetWriter; public void sendPacket( Packet packet ) { if (!isConnected())

动机

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);
    }
}
我需要额外的眼睛来确认我能够调用这个方法XMPPConnection.sendPacket( 数据包)同时进行。对于我当前的代码,我以串行方式调用一个可调用列表(最多3个)。每个可调用对象在一个XMPP连接上发送/接收XMPP数据包。我计划通过分离多个线程来并行化这些可调用项&每个可调用项都将在共享XMPPConnection上调用sendpackage,而无需同步

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();
    }
}
class PacketWriter
{
公共无效发送包(数据包)
{
如果(!完成){
//为新数据包调用拦截器
//就要发送了,拦截器
//可以修改数据包的内容。
处理器拦截器(数据包);
试一试{
队列放置(数据包);
}
捕获(中断异常ie){
即printStackTrace();
返回;
}
已同步(队列){
queue.notifyAll();
}
//处理数据包编写器侦听器
//使用发送线程,因此
//听众反应很快。
processListeners(数据包);
}
受保护的PacketWriter(XMPPConnection)
{
this.queue=newarrayblockingqueue(500,true);
这个连接=连接;
init();
}
}
我的结论


由于PacketWriter正在使用BlockingQueue,因此我打算从多个线程调用sendPacket没有问题。我说的对吗?

您在这里提供的信息不够

我们不知道以下内容是如何实现的:

  • 处理器拦截器
  • 进程侦听器
谁读取/写入“done”变量?如果一个线程将其设置为true,那么所有其他线程都会自动失败

快速浏览一下,这看起来不是线程安全的,但无法从您发布的内容中确定

其他问题:

  • 当PacketWriter仅用于一个方法时,为什么它是XMPPConnection的类成员
  • 为什么PacketWriter有一个XMPPConnection成员变量而不使用它

如果可以限制为java 5+.</p >,可以考虑使用阻塞队列。 从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();
   }
 }
对于您的使用,您的真正发送者(实际连接的持有者)是消费者,而包准备者/发送者是生产者

另一个有趣的想法是,您可以使用PriorityBlockingQueue来允许闪存覆盖在任何其他等待的数据包之前发送的XMPP数据包


此外,Glen在设计上的观点也是很好的。您可能想看看Smack API(),而不是创建自己的API。

是的,您可以从不同的线程发送数据包,而不会出现任何问题

Smack阻塞队列是因为您不能让不同的线程同时写入输出流。Smack负责以每包粒度写入输出流,从而同步输出流

Smack实现的模式只是一个典型的生产者/消费者并发模式。您可能有多个生产者(您的线程),只有一个消费者(Smack的PacketWriter在自己的线程中运行)

问候