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大量的時間片。
至此問題完美解決,特此記錄。
(有人說循環間用sleep休眠就可以解決,但是本人不太喜歡用sleep,隨便用sleep的都是耍流氓)
總結
以上是生活随笔為你收集整理的Java socket编程 CPU占用率高的问题解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1044 mysql_MYSQL 有ER
- 下一篇: 自定义带取景框的camera