<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    一段好玩的測試LinkedBlockingQueue.poll超時(shí)的程序

    在產(chǎn)品中有碰到過使用LinkedBlockingQueue.poll時(shí)超時(shí)很不準(zhǔn)的現(xiàn)象,關(guān)鍵是這不是一般的不準(zhǔn),如果只是一點(diǎn)點(diǎn)不準(zhǔn)的話也就勉強(qiáng)接受了,例如指定poll的超時(shí)時(shí)間為100ms,但最終執(zhí)行.poll這段代碼就花費(fèi)了8000ms的現(xiàn)象,這篇blog就是展示下通過一段小小的代碼來重現(xiàn)這樣的現(xiàn)象,畢竟沒有重現(xiàn)是無法證明為什么會出現(xiàn)這樣的現(xiàn)象的。

    由于在出現(xiàn)這個(gè)現(xiàn)象的時(shí)候有看到過OutOfMemory的錯(cuò),雖然java進(jìn)程沒退出,但猜想可能是這個(gè)原因造成的,于是寫了下面這段代碼:
    public static void main(String[] args) throws Exception{
            
    long beginTime=System.currentTimeMillis();
            Map
    <String, byte[]> cache=new HashMap<String, byte[]>();
            
    for (int i = 0; i < 1000000; i++) {
                cache.put(String.valueOf(i),
    new byte[500]);
            }
            CountDownLatch latch
    =new CountDownLatch(25);
            
    for (int i = 0; i < 5; i++) {
                
    for (int j = 0; j < 5; j++) {
                    Thread thread
    =new Thread(new TestThread(latch));
                    thread.start();
                }
            }
            latch.await();
            
    long endTime=System.currentTimeMillis();
            System.out.println(
    "總共執(zhí)行時(shí)間:"+(endTime-beginTime));
        }
        
        
    static class TestThread implements Runnable{

            
    private CountDownLatch latch;
            
            
    public TestThread(CountDownLatch latch){
                
    this.latch=latch;
            }
            
            
    public void run(){
                BlockingQueue
    <String> queue=new LinkedBlockingQueue<String>(1);
                
    try{
                    
    for (int i = 0; i < 5; i++) {
                        
    long beginTime=System.currentTimeMillis();
                        queue.poll(
    100, TimeUnit.MILLISECONDS);
                        
    long endTime=System.currentTimeMillis();
                        
    long consumeTime=endTime-beginTime;
                        
    if(consumeTime>200)
                            System.out.println(
    "獲取queue的時(shí)間為:"+consumeTime);
                        @SuppressWarnings(
    "unused")
                        
    byte[] bytesNew=new byte[25506000];
                    }
                }
                
    catch(Exception e){
                    ;
                }
                latch.countDown();
            }
            
        }

    啟動上面程序時(shí),將jvm參數(shù)設(shè)置為-Xms640M -Xmx640M,運(yùn)行后,應(yīng)該會看到有很多queue.poll執(zhí)行超過200ms的現(xiàn)象,甚至?xí)霈F(xiàn)8000ms的現(xiàn)象。

    上面整段程序的寫法就是用大量的小對象占據(jù)old generation,然后啟動多個(gè)線程,每個(gè)線程運(yùn)行的時(shí)候new一個(gè)大的對象,讓其產(chǎn)生有可能直接從new generation分配到old generation,從而導(dǎo)致Full GC頻繁執(zhí)行,里面的byte數(shù)組的大小的原則為:塞滿內(nèi)存,產(chǎn)生Full GC,但又盡量不讓應(yīng)用出現(xiàn)OutOfMemory,或者說不出現(xiàn)過于頻繁的OutOfMemory,避免jvm crash。

    從上面程序的運(yùn)行效果來看,當(dāng)jvm內(nèi)存消耗的很嚴(yán)重的情況下,poll的超時(shí)是沒法準(zhǔn)的,其實(shí)分析下原因,還是挺正常的:
    1、jvm內(nèi)存消耗嚴(yán)重的情況下,Minor GC和Full GC瘋狂執(zhí)行,導(dǎo)致了應(yīng)用的執(zhí)行不斷的被暫停,因此當(dāng)線程已經(jīng)進(jìn)入poll等待后,這個(gè)線程沒有機(jī)會被執(zhí)行,導(dǎo)致當(dāng)其有機(jī)會執(zhí)行時(shí),早就超過了指定的超時(shí)時(shí)間,因此其超時(shí)不準(zhǔn)并不是本身的機(jī)制導(dǎo)致的,而是jvm GC造成的多次暫停;
    2、多次暫停的情況下,jvm需要不斷的調(diào)度恢復(fù)線程,這需要消耗很多的資源,而且切換多了Swap空間很容易不夠用,最終導(dǎo)致jvm crash。

    posted on 2009-03-12 16:52 BlueDavy 閱讀(7813) 評論(4)  編輯  收藏 所屬分類: Java

    評論

    # re: 一段好玩的測試LinkedBlockingQueue.poll超時(shí)的程序 2009-03-12 20:23 lizongbo

    這個(gè)應(yīng)該和jdk的具體版本有關(guān),不知道你們用的具體哪個(gè)版本的jdk。
    我剛才試了一下用不同版本jdk運(yùn)行的效果:
    各版本的耗時(shí)不一樣:
    1.7.0-nio2 ,基本都在359左右。
    1.6.0_11 ,基本都在453左右。
    1.5.0_14,基本在2359左右。


    前段時(shí)間我們就是因?yàn)閖dk的gc問題,對所有的服務(wù)器都進(jìn)行了jdk升級到j(luò)dk1.6.0_12。

      回復(fù)  更多評論   

    # re: 一段好玩的測試LinkedBlockingQueue.poll超時(shí)的程序 2009-03-12 20:28 lizongbo

    漏了補(bǔ)充說明,只在jdk1.5的時(shí)候運(yùn)行出現(xiàn)了java.lang.OutOfMemoryError,而jdk1.6和jdk1.7都沒出現(xiàn)OutOfMemoryError.
      回復(fù)  更多評論   

    # re: 一段好玩的測試LinkedBlockingQueue.poll超時(shí)的程序 2009-03-12 20:34 BlueDavy

    @lizongbo
    多謝,:),我之前還只在1.5.0_10上跑過,看來越新的java版本,性能確實(shí)越好,呵呵  回復(fù)  更多評論   

    # re: 一段好玩的測試LinkedBlockingQueue.poll超時(shí)的程序 2009-03-12 22:50 岑文初

    觀察過,1.5肯定是不回收的,它的一個(gè)鎖信號量,1.6回收比較慢,要到一定的內(nèi)存占用比例才會去Gc。SIP最早時(shí)候的內(nèi)存泄露就是這個(gè)問題。  回復(fù)  更多評論   

    公告

     









    feedsky
    抓蝦
    google reader
    鮮果

    導(dǎo)航

    <2009年3月>
    22232425262728
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    統(tǒng)計(jì)

    隨筆分類

    隨筆檔案

    文章檔案

    Blogger's

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 毛片免费观看的视频在线| 成人免费午间影院在线观看| 久久精品国产亚洲AV大全| 免费大片黄在线观看yw| 久久久久亚洲国产AV麻豆| 国产亚洲精品国看不卡| 91精品全国免费观看含羞草| 亚洲精品国产第一综合99久久| 天堂亚洲免费视频| 91高清免费国产自产拍2021| 亚洲国产精品精华液| 亚洲色成人网站WWW永久| 成人免费AA片在线观看| 免费视频成人国产精品网站 | 久久亚洲精品成人AV| 国产精品无码一区二区三区免费 | 亚洲av产在线精品亚洲第一站| 国产成人无码免费视频97 | 亚洲国产精品18久久久久久| 中国亚洲女人69内射少妇| 毛片在线免费视频| 久久九九全国免费| 黑人粗长大战亚洲女2021国产精品成人免费视频 | 黄色成人网站免费无码av| 久青草视频在线观看免费| 亚洲午夜无码毛片av久久京东热| 在线观看国产区亚洲一区成人 | 9i9精品国产免费久久| 亚洲成a人片在线不卡| 精品亚洲永久免费精品| 免费毛片在线播放| 成年人网站免费视频| 丁香花在线视频观看免费| 激情吃奶吻胸免费视频xxxx| 亚洲伦理一二三四| 香蕉蕉亚亚洲aav综合| 亚洲欧洲久久av| 日日操夜夜操免费视频 | 亚洲AV一宅男色影视| yy6080久久亚洲精品| 成年人免费观看视频网站|