Java socket编程 CPU占用率高的问题解决

本人用Java socket编程,多线程程序,发现CPU占用率非常高,经过一番研究,问题解决,特记录如下。
首先上问题代码(代码同时实现了超时机制):

/**
* 发送完毕以后等待服务器返回数据的函数 实现了超时机制
*/
public Boolean awaitReturnOLD(int timeout) {
Boolean result = false;
// 上锁:实现超时机制第一步
expectedArriveLatch = new CountDownLatch(1);
//任务放到线程:实现超时机制第二步
new Thread(new Runnable() {
@Override
public void run() {
pullBuffer = null;
int count = 0;
while (true) {
try {
// 读信息
while (count == 0)
count = in.available();
byte[] b = new byte[count];
in.read(b);
LogUtils.debug(LABEL, "Thread get:" + new String(b));

// 叠加到接收缓冲区
pullBuffer = ArrayUtils.addAll(pullBuffer, b);
//判断是否已经收到想要的结果(约定结果以两个##包裹) 自己写的函数简单判断字符#的数量
if (PublicUtils.getByteCount(pullBuffer) >= 2)
break;
} catch (IOException e) {
LogUtils.debug(LABEL, "AwaitReturn failed.");
}
}
// 收到了想要的数据,解锁
expectedArriveLatch.countDown();
}
}).start();

// 等待解锁:实现超时机制第三步
try {
result = expectedArriveLatch.await(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
LogUtils.error(LABEL, e);
}
//正常收到则result = true 超时结束则result = fasle
return result;
}
以上代码单线程运行的时候,工作正常,多线程运行的时候,发现CPU占用率居高不下 。
参照以下文章内容,使用jstack和Process Explorer对程序进行了分析:
https://blog.csdn.net/hexin373/article/details/8846919?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
问题定位在如下一行代码:
try {
// 读信息
while (count == 0)
count = in.available();
byte[] b = new byte[count];
in.read(b);
深入了解,看一下官方API解释:public int available() throws IOException 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。这个方法的调用是立即返回的,于是乎在返回数据还没有到来的情况下,这个代码片段像极了死循环,所以才导致CPU巨高不下。
找到问题,就好解决了,改进代码片段如下:
while ((len = in.read(buf)) != -1) {
byte[] tmp = ArrayUtils.subarray(buf, 0, len);
pullBuffer = ArrayUtils.addAll(pullBuffer, tmp);
in.read(buf)方法是阻塞式的,会一直等到至少有一个字节数据的到来,阻塞方式不需要CPU轮询,不会占据CPU大量的时间片。
至此问题完美解决,特此记录。
【Java socket编程 CPU占用率高的问题解决】(有人说循环间用sleep休眠就可以解决,但是本人不太喜欢用sleep,随便用sleep的都是耍流氓)

    推荐阅读