动机
我希望额外的目光确认我能够调用此方法 XMPPConnection.sendPacket( 数据包)同时发生。对于我当前的代码,我以串行方式调用Callables列表(最多3个)。每个Callable在一个XMPPConnection上发送/接收XMPP数据包。我计划通过分离多个线程和&来并行化这些Callables。每个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,因此我打算从多个线程调用sendPacket没有问题。我是对的吗?
答案 0 :(得分:2)
是的,您可以毫无问题地从不同的线程发送数据包。
Smack阻塞队列是因为你不能做的是让不同的线程同时写输出流。 Smack负责通过以每个数据包粒度写入来同步输出流。
Smack实现的模式只是一种典型的生产者/消费者并发模式。你可能有几个生产者(你的线程)和只有一个消费者(Smack的PacketWriter在它自己的线程中运行)。
问候。
答案 1 :(得分:0)
您在此处未提供足够的信息。
我们不知道如何实施以下内容:
谁读/写'完成'变量?如果一个线程将其设置为true,那么所有其他线程将无声地失败。
从快速浏览一下,这看起来并不安全,但是没有办法确定你发布的内容。
其他问题:
答案 2 :(得分: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();
}
}
对于您的使用,您的真实发件人(实际连接的持有者)是消费者,而数据包准备者/发件人是生产者。
另一个有趣的想法是,您可以使用PriorityBlockingQueue来允许闪存覆盖在任何其他等待数据包之前发送的XMPP数据包。
此外,格伦在设计上的观点是好点。您可能想要查看Smack API(http://www.igniterealtime.org/projects/smack/),而不是创建自己的。