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

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

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

    新的起點(diǎn) 新的開始

    快樂生活 !

    深入淺出多線程(4)對(duì)CachedThreadPool OutOfMemoryError問題的一些想法

        接系列3,在該系列中我們一起探討一下CachedThreadPool。
        線程池是Conncurrent包提供給我們的一個(gè)重要的禮物。使得我們沒有必要維護(hù)自個(gè)實(shí)現(xiàn)的心里很沒底的線程池了。但如何充分利用好這些線程池來加快我們開發(fā)與測(cè)試效率呢?當(dāng)然是知己知彼。本系列就說說對(duì)CachedThreadPool使用的一下問題。
        下面是對(duì)CachedThreadPool的一個(gè)測(cè)試,程序有問題嗎?
    package net.blogjava.vincent;

    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;

    public class CachedThreadPoolIssue {

        
    /**
         * 
    @param args
         
    */
        
    public static void main(String[] args) {
            
            ExecutorService es 
    = Executors.newCachedThreadPool();
            
    for(int i = 1; i<8000; i++)
                es.submit(
    new task());

        }

    }
    class task implements Runnable{

        @Override
        
    public void run() {
        
    try {
            Thread.sleep(
    4000);
        } 
    catch (InterruptedException e) {
            
    // TODO Auto-generated catch block
            e.printStackTrace();
        }
            
        }
        
    }
    如果對(duì)JVM沒有特殊的設(shè)置,并在Window平臺(tái)上,那么就會(huì)有一下異常的發(fā)生:
    Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
        at java.lang.Thread.start0(Native Method)
        at java.lang.Thread.start(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.addIfUnderMaximumPoolSize(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)
        at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
        at net.blogjava.vincent.CachedThreadPoolIssue.main(CachedThreadPoolIssue.java:19)
    看看Doc對(duì)該線程池的介紹:
    Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.

    有以下幾點(diǎn)需要注意:
    1. 指出會(huì)重用先前的線程,不錯(cuò)。
    2. 提高了短Task的吞吐量。
    3. 線程如果60s沒有使用就會(huì)移除出Cache。

    好像跟剛才的錯(cuò)誤沒有關(guān)系,其實(shí)就第一句話說了問題,它會(huì)按需要?jiǎng)?chuàng)建新的線程,上面的例子一下提交8000個(gè)Task,意味著該線程池就會(huì)創(chuàng)建8000線程,當(dāng)然,這遠(yuǎn)遠(yuǎn)高于JVM限制了。
    注:在JDK1.5中,默認(rèn)每個(gè)線程使用1M內(nèi)存,8000M !!! 可能嗎!!

    所以我感覺這應(yīng)該是我遇到的第一個(gè)Concurrent不足之處,既然這么設(shè)計(jì),那么就應(yīng)該在中Doc指出,應(yīng)該在使用避免大量Task提交到給CachedThreadPool.
    可能讀者不相信,那么下面的例子說明了他創(chuàng)建的Thread。
    在ThreadPoolExecutor提供的API中,看到它提供beforeExecute 和afterExecute兩個(gè)可以在子類中重載的方法,該方法在線程池中線程執(zhí)行Task之前與之后調(diào)用。所以我們?cè)赽eforeExexute中查看目前線程編號(hào)就可以確定目前的線程數(shù)目.
    package net.blogjava.vincent;

    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.SynchronousQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;

    public class CachedThreadPoolIssue {

        
    /**
         * 
    @param args
         
    */
        
    public static void main(String[] args) {
            
            ExecutorService es 
    = new LogThreadPoolExecutor(0, Integer.MAX_VALUE,
                    
    60L, TimeUnit.SECONDS,
                    
    new SynchronousQueue<Runnable>());
            
    for(int i = 1; i<8000; i++)
                es.submit(
    new task());

        }

    }
    class task implements Runnable{

        @Override
        
    public void run() {
        
    try {
            Thread.sleep(
    600000);
        } 
    catch (InterruptedException e) {
            
    // TODO Auto-generated catch block
            e.printStackTrace();
        }
            
        }
        
    }
    class LogThreadPoolExecutor extends ThreadPoolExecutor{

        
    public LogThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
                
    long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
            
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        }
        
    protected void beforeExecute(Thread t, Runnable r) { 
            System.out.println(t.getName());
        }
        
    protected void afterExecute(Runnable r, Throwable t) {
        }
        
    }
    測(cè)試結(jié)果如圖:

    當(dāng)線程數(shù)達(dá)到5592是,只有在任務(wù)管理器Kill該進(jìn)程了。

    如何解決該問題呢,其實(shí)在剛才實(shí)例化時(shí)就看出來了,只需將
    new LogThreadPoolExecutor(0, Integer.MAX_VALUE,
                    60L, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>());
    Integer.MAX_VALUE 改為合適的大小。對(duì)于該參數(shù)的含義,涉及到線程池的實(shí)現(xiàn),將會(huì)在下個(gè)系列中指出。
    當(dāng)然,其他的解決方案就是控制Task的提交速率,避免超過其最大限制。

    posted on 2008-09-03 21:50 advincenting 閱讀(7904) 評(píng)論(2)  編輯  收藏

    評(píng)論

    # re: 深入淺出多線程(4)對(duì)CachedThreadPool OutOfMemoryError問題的一些想法 2008-09-04 08:59 dennis

    實(shí)際應(yīng)用中我想用到CachedThreadPool的機(jī)會(huì)不多,通常情況下都推薦使用FixedThreadPool以規(guī)定線程數(shù)上限,也利于調(diào)優(yōu)  回復(fù)  更多評(píng)論   

    # re: 深入淺出多線程(4)對(duì)CachedThreadPool OutOfMemoryError問題的一些想法 2008-09-29 11:38 niuren

    同意, CachedThreadPool內(nèi)部使用的是SynchronousQueue, 感覺這個(gè)結(jié)構(gòu)本身就決定了CachedThreadPool很慢。所以一般情況下還是用FixedThreadPool或自定義的ThreadPoolExecut  回復(fù)  更多評(píng)論   


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    公告

    Locations of visitors to this pageBlogJava
  • 首頁
  • 新隨筆
  • 聯(lián)系
  • 聚合
  • 管理
  • <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    統(tǒng)計(jì)

    常用鏈接

    留言簿(13)

    隨筆分類(71)

    隨筆檔案(179)

    文章檔案(13)

    新聞分類

    IT人的英語學(xué)習(xí)網(wǎng)站

    JAVA站點(diǎn)

    優(yōu)秀個(gè)人博客鏈接

    官網(wǎng)學(xué)習(xí)站點(diǎn)

    生活工作站點(diǎn)

    最新隨筆

    搜索

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 久久久久亚洲AV成人无码网站| 四虎影在线永久免费四虎地址8848aa| 国内精品99亚洲免费高清| 国产亚洲成在线播放va| 日韩免费视频播放| 18禁亚洲深夜福利人口| 国产又大又长又粗又硬的免费视频| 亚洲免费网站观看视频| 天天看免费高清影视| 亚洲丁香婷婷综合久久| 国产精品久久免费视频| 污视频网站免费观看| 亚洲精品无码专区2| A毛片毛片看免费| 久久精品国产亚洲夜色AV网站| 久久青草91免费观看| 亚洲毛片无码专区亚洲乱| 免费精品国偷自产在线在线| 亚洲av永久无码嘿嘿嘿| 免费的涩涩视频在线播放| 女人裸身j部免费视频无遮挡| 国产亚洲日韩在线三区| 5555在线播放免费播放| 亚洲欧洲另类春色校园网站| 国产精品无码一区二区三区免费| 特级无码毛片免费视频| 亚洲一区无码中文字幕| 亚洲高清视频免费| 亚洲国产区男人本色| 亚洲色欲久久久综合网| 美女内射无套日韩免费播放 | 亚洲国产精品无码专区| 最近中文字幕大全免费视频| 中文字幕亚洲综合小综合在线| 国产成人免费网站在线观看 | 男性gay黄免费网站| 亚洲综合网站色欲色欲| 99视频全部免费精品全部四虎| 亚洲av成本人无码网站| 久久99国产亚洲高清观看首页| 日本妇人成熟免费中文字幕|