服務端原本有個定時任務對一個集合ArrayList 中的消息做處理。 因為考慮到處理消息是先進先出原則,所以優化的時候考慮改用ConcurrentLinkedQueue 當時沒仔細深入研究過這個集合就匆匆上線了。結果剛上線第二天就出問題了。服務端一次優化演變成了一個缺陷,還好及時回退了版本,后果才不是很嚴重。
回退后對ConcurrentLinkedQueue 做了一個簡單的測試代碼如下:
- import java.util.concurrent.ConcurrentLinkedQueue;
- import java.util.concurrent.CountDownLatch;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class ConcurrentLinkedQueueTest {
- private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
- private static int count = 100000;
- private static int count2 = 2; // 線程個數
- private static CountDownLatch cd = new CountDownLatch(count2);
- public static void dothis() {
- for (int i = 0; i < count; i++) {
- queue.offer(i);
- }
- }
- public static void main(String[] args) throws InterruptedException {
- long timeStart = System.currentTimeMillis();
- ExecutorService es = Executors.newFixedThreadPool(4);
- ConcurrentLinkedQueueTest.dothis();
- for (int i = 0; i < count2; i++) {
- es.submit(new Poll());
- }
- cd.await();
- System.out.println("cost time "
- + (System.currentTimeMillis() - timeStart) + "ms");
- es.shutdown();
- }
- static class Poll implements Runnable {
- @Override
- public void run() {
- // while (queue.size()>0) {
- while (!queue.isEmpty()) {
- System.out.println(queue.poll());
- }
- cd.countDown();
- }
- }
- }
運行結果:
costtime 2360ms
改用while (queue.size()>0)后
運行結果:
cost time 46422ms
結果居然相差那么大,看了下ConcurrentLinkedQueue的API 原來.size() 是要遍歷一遍集合的,難怪那么慢,所以盡量要避免用size而改用isEmpty().
總結了下, 在單位缺乏性能測試下,對自己的編程要求更加要嚴格,特別是在生產環境下更是要小心謹慎。
