android+io阻塞,AndroidPN的阻塞IO

? ? ? androidPN服务端用的是mina,略去不表,客户端的socket通讯用的是asmack,期间使用xmpp协议通讯,这个xmpp通用是通用了,但用的是xml格式互发,之间不得不加了一堆的xml解析,大部分篇幅都是干这个,对此没多大兴趣,这里只是简单记录一下阅读源码中client与server的阻塞读写,寻找可以借鉴之处。

? ? ?客户端启动之后,负责管理连接的XMPPConnection初始化:

if (isFirstInitialization) {

packetWriter = new PacketWriter(this);

packetReader = new PacketReader(this);

? ?分别负责读写。然后启动二者:

// Start the packet writer. This will open a XMPP stream to the server

packetWriter.startup();

// Start the packet reader. The startup() method will block until we

// get an opening stream packet back from server.

packetReader.startup();

// Make note of the fact that we‘re now connected.

connected = true;

? ?

先来看packetWriter是如何向服务器发送数据的,它的初始化方法

protected void init() {

this.writer = connection.writer;

done = false;

writerThread = new Thread() {

public void run() {

writePackets(this);

}

};

writerThread.setName("Smack Packet Writer (" + connection.connectionCounterValue + ")");

writerThread.setDaemon(true);

}

开一个守候线程writeThread,跑writePackets(this),该方法主要代码:

// Write out packets from the queue.

while (!done && (writerThread == thisThread)) {

Packet packet = nextPacket();

if (packet != null) {

writer.write(packet.toXML());

if (queue.isEmpty()) {

writer.flush();

}

}

}

?其中queue,线程安全:

private final BlockingQueue queue;

?queue中有数据就write到服务器,如果没数据,阻塞在nextPacket():

private Packet nextPacket() {

Packet packet = null;

// Wait until there‘s a packet or we‘re done.

while (!done && (packet = queue.poll()) == null) {

try {

synchronized (queue) {

queue.wait();

}

}

catch (InterruptedException ie) {

// Do nothing

}

}

return packet;

}

?看看,queue.wait(),写线程阻塞于此,省电! 既然有wait(),必然有notifyAll():

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.

connection.firePacketInterceptors(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.

connection.firePacketSendingListeners(packet);

}

}

?当其他线程把要写的数据put进queue时,writerThread即被唤醒,继续运作,标准的生产消费模式。这个过程还是比较简单的,一目了然,相比之下PacketReader就不那么省心。

?

? ? PacketReader初始化:

protected void init() {

//...

readerThread = new Thread() {

public void run() {

parsePackets(this);

}

};

//...

resetParser();

}

?接着看parsePackets:

private void parsePackets(Thread thread) {

try {

int eventType = parser.getEventType();

do {

if (eventType == XmlPullParser.START_TAG) {

//...

//...很长很长,都在xml纠结

//...

eventType = parser.next();

} while (!done && eventType != XmlPullParser.END_DOCUMENT && thread == readerThread);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值