当我们使用套接字通道写入方法写入数据时。这需要花费太多时间来处理小字节数据。例如,如果许多客户端连接到我的应用程序,则需要43950 ms来写入16249字节数据。它尝试442次来写上面的数据。
public static void writeBytesFixedLength(SocketChannel sChannel, String msg){
ByteBuffer writeBuffer = ByteBuffer.allocate(msg.length()*2);
writeBuffer.put(msg.getBytes());
writeBuffer.flip();
long nbytes = 0;
long toWrite = writeBuffer.remaining();
int sleepCount = 0;
int loopCount = 0;
int sleepTime = 50;
int sumSleepCount = 0;
int sumSleepTime = 0;
try
{
int count = 0;
while (nbytes != toWrite) {
count= sChannel.write(writeBuffer);
nbytes +=count;
loopCount += 1;
try {
if(count == 0){
OSUsage();
MainImapServer.printThreadStatus();
sleepCount += 1;
sumSleepCount += 1;
if(sleepCount == 4){
sleepTime = 50;
sleepCount =1;
}
sumSleepTime += sleepTime*sleepCount;
Thread.sleep(sleepTime*sleepCount);
}
}
catch (InterruptedException e) {}
}
}
catch (ClosedChannelException cce) {}
catch (Exception e) {}
if(sumSleepCount >3)
logger.info("Send buffer is full: Total Byte: "+ toWrite+ " sleepCount: "+sumSleepCount +" sleepTime: "+sumSleepTime+ " loopCount: "+ loopCount);
}
请提出一些建议来解决这个问题
提前致谢
答案 0 :(得分:0)
你在这里断言你的套接字通道write()
调用是阻塞的,并且它返回零。这些断言是相互矛盾的。你误会了。 API规范和底层机制都使这成为不可能。 阻止或它返回零。
编辑从您的代码中可以看出它返回零。这意味着几件事:
当你得到零时,你应该为OP_WRITE注册一个Selector
的频道,调用select(),
并在频道变为可写时重试写入;如果写入成功,请取消注册OP_WRITE。这sleep()
没有废话。
显然你需要阅读Oracle NIO教程。或者扔掉它并使用阻止模式。 java.net
甚至。它简单得多。