使用ConcurrentLinkedQueue慘痛的教訓


服務端原本有個定時任務對一個集合ArrayList 中的消息做處理。 因為考慮到處理消息是先進先出原則,所以優化的時候考慮改用ConcurrentLinkedQueue 當時沒仔細深入研究過這個集合就匆匆上線了。結果剛上線第二天就出問題了。服務端一次優化演變成了一個缺陷,還好及時回退了版本,后果才不是很嚴重。

回退后對ConcurrentLinkedQueue 做了一個簡單的測試代碼如下:

 

[java] view plain copy
 
  1. import java.util.concurrent.ConcurrentLinkedQueue;  
  2. import java.util.concurrent.CountDownLatch;  
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5. public class ConcurrentLinkedQueueTest {  
  6.     private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();  
  7.     private static int count = 100000;  
  8.     private static int count2 = 2// 線程個數  
  9.     private static CountDownLatch cd = new CountDownLatch(count2);  
  10.     public static void dothis() {  
  11.         for (int i = 0; i < count; i++) {  
  12.             queue.offer(i);  
  13.         }  
  14.     }  
  15.     public static void main(String[] args) throws InterruptedException {  
  16.         long timeStart = System.currentTimeMillis();  
  17.         ExecutorService es = Executors.newFixedThreadPool(4);  
  18.         ConcurrentLinkedQueueTest.dothis();  
  19.         for (int i = 0; i < count2; i++) {  
  20.             es.submit(new Poll());  
  21.         }  
  22.         cd.await();  
  23.         System.out.println("cost time "  
  24.                 + (System.currentTimeMillis() - timeStart) + "ms");  
  25.         es.shutdown();  
  26.     }  
  27.     static class Poll implements Runnable {  
  28.         @Override  
  29.         public void run() {  
  30. //          while (queue.size()>0) {  
  31.             while (!queue.isEmpty()) {  
  32.                 System.out.println(queue.poll());  
  33.             }  
  34.             cd.countDown();  
  35.         }  
  36.     }  
  37. }  

 

運行結果:

costtime 2360ms

 

改用while (queue.size()>0)后

運行結果:

cost time 46422ms

 

結果居然相差那么大,看了下ConcurrentLinkedQueue的API 原來.size() 是要遍歷一遍集合的,難怪那么慢,所以盡量要避免用size而改用isEmpty().

總結了下, 在單位缺乏性能測試下,對自己的編程要求更加要嚴格,特別是在生產環境下更是要小心謹慎。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM