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

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

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

    隨筆-128  評論-55  文章-5  trackbacks-0

    http://sunnylocus.iteye.com/blog/538282

    當一個單線程化的控制臺程序因為未捕獲的異常終止的時候,程序停止運行,并生了棧追蹤,這與典型的程序輸出不同,當一個程序發生了異常說明有不穩定的因素存在。如果并發程序中線程失敗就沒那么容易發現了。棧追蹤可能會從控制臺輸出,但是沒有人會去一直在看控制臺,并且,當線程失敗的時候,應用程序可能看起來仍在工作。就象程序能跑在50個線程池上,也能夠跑在49個線程的線程池上,區別在于50個人干的活要比49個人干的活要多的多。

      導致線程死亡的的最主要的原因是RuntimeException。因為這些異常表明一個程序錯誤或者不可修復的錯誤,它們不著順著棧的調用傳遞,此時,默認的行為是在控制臺打印棧追蹤的信息,并終止線程。

      我們舉個例子,將奴隸主比作是你寫的程序,奴隸比作是線程。假如你是奴隸主,你手下有5名奴隸,你分派他們一項任務去將不斷開采來的石頭搬到某個地方。如果中途有奴隸逃跑,那么搬運石頭的效率就會下降,如果你沒有措施發現奴隸逃跑,最后連一個奴隸也沒有了,沒有人再去搬石頭了。當你發現程序有問題,比如程序剛啟動的時候處理速度很快,以后越跑越慢,最后完全停止了,你可能不知道問題出在哪兒,其實這都是因為線程泄露引起的。想解決奴隸逃跑問題,不難,給每個奴隸戴上個報警器,一逃跑報警器就給你發信息,告訴哪個奴隸,因為什么原因逃跑了,可以根據需要再增加一名奴隸,讓搬石頭的奴隸數量始終維持在5名或著將信息記錄到文件,便于分析導致線程泄露的原意改進程序。ok,我們用代碼說話

    1、定義好報警器

    Java代碼 復制代碼 收藏代碼
    1. package com.bill99.thread.test;   
    2.   
    3. import java.lang.Thread.UncaughtExceptionHandler;   
    4.   
    5. //將泄露的線程信息輸出到控制臺   
    6. public class UEHLogger implements UncaughtExceptionHandler {   
    7.     public void uncaughtException(Thread t, Throwable e) {   
    8.         System.out.println(String.format("不好了,有奴隸逃跑了!奴隸姓名:%1$s,編號:%2$s,逃跑原因:%3$s", t.getName(),t.getId(),e.getMessage()));   
    9.         System.out.println("還剩"+HelotPool.helotPool.getActiveCount()+"個奴隸");   
    10.     }   
    11. }  

      

    2、我們先建立一個奴隸工廠,每名奴隸出工廠的時候都會有一個報警器

        

    Java代碼 復制代碼 收藏代碼
    1. package com.bill99.thread.test;   
    2.   
    3. import java.util.concurrent.ThreadFactory;   
    4. //奴隸制造工廠   
    5. public class HelotFactory implements ThreadFactory {   
    6.     private volatile int helotId=0;//奴隸編號   
    7.     //產生一個新奴隸   
    8.     public Thread newThread(Runnable r) {   
    9.         Thread helotThread = new Thread(r);   
    10.         helotThread.setName("helot-Thread-"+gethelotId());//設置奴隸姓名   
    11.         helotThread.setUncaughtExceptionHandler(new UEHLogger());//UEHLogger就是報警器   
    12.         return helotThread;   
    13.     }   
    14.     private int gethelotId(){   
    15.         return ++helotId;   
    16.     }   
    17. }  

     3、奴隸逃跑測試,看看是否會觸發報警器

    Java代碼 復制代碼 收藏代碼
    1. package com.bill99.thread.test;   
    2.   
    3. import java.util.concurrent.ThreadFactory;   
    4. //奴隸逃跑測試   
    5. public class HelotEscapeTest {   
    6.     private ThreadFactory factory = new HelotFactory();   
    7.     private Thread helotThread = null;   
    8.        
    9.     public HelotEscapeTest(){   
    10.         Runnable task = new Runnable() {   
    11.             int stoneNum=1;   
    12.             public void run() {   
    13.                 while(!Thread.interrupted()){   
    14.                     System.out.println(helotThread.getName()+" 搬第"+stoneNum+"塊石頭..");   
    15.                     stoneNum++;   
    16.                     try{   
    17.                         Thread.sleep(500);   
    18.                     } catch(InterruptedException e){e.printStackTrace();}   
    19.                     if(stoneNum>100){   
    20.                         throw new RuntimeException("又餓又累沒力氣搬石頭了");   
    21.                     }   
    22.                 }   
    23.             }   
    24.         };   
    25.         helotThread = factory.newThread(task);   
    26.     }   
    27.     //開始干活   
    28.     public void startWork(){   
    29.         helotThread.start();   
    30.     }   
    31.     public static void main(String[] args) {   
    32.         HelotEscapeTest test = new HelotEscapeTest();   
    33.         test.startWork();   
    34.     }   
    35. }  

     運行程序后,奴隸在搬完100塊石頭后不干了,報警器給出提示信息

       不好了,有奴隸逃跑了!奴隸姓名:helot-Thread-1,編號:7,逃跑原因:又餓又累沒力氣搬石頭了

    這樣我就能找出線程泄露的原因了。如果在線程池中發生了泄露是否也能記錄?

    4、奴隸池測試

    Java代碼 復制代碼 收藏代碼
    1. package com.bill99.thread.test;   
    2.   
    3. import java.util.Random;   
    4. import java.util.concurrent.BlockingQueue;   
    5. import java.util.concurrent.LinkedBlockingQueue;   
    6. import java.util.concurrent.ThreadFactory;   
    7. import java.util.concurrent.ThreadPoolExecutor;   
    8. import java.util.concurrent.TimeUnit;   
    9.   
    10. public class HelotPoolTest {   
    11.        
    12.     public static ThreadPoolExecutor helotPool;   
    13.     private int helotNum= 5;  //奴隸數   
    14.     private Random random = new Random(100);   
    15.        
    16.     private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();   
    17.        
    18.     public HelotPoolTest() {   
    19.         ThreadFactory factory = new HelotFactory();   
    20.         helotPool = new ThreadPoolExecutor( helotNum,helotNum,1000,TimeUnit.SECONDS,queue,factory);   
    21.     }   
    22.     //分配任務   
    23.     public void assignTask(){   
    24.         final int MAX=100;   
    25.         final int MIN=10;   
    26.         Runnable task = null;   
    27.         for(int j=0;j<20;j++){   
    28.             task = new Runnable() {   
    29.                 int stoneNum = random.nextInt(MAX - MIN + 1) + MIN;// 生成10~100范圍的隨機數   
    30.                 public void run() {   
    31.                     for (int i = 1; i <= stoneNum; i++) {   
    32.                         System.out.println(Thread.currentThread().getName() + " 搬完"+ i + "塊石頭");   
    33.                         if (i == 60) {   
    34.                             throw new RuntimeException("搬完第60塊石頭不干了");   
    35.                         }   
    36.                         try{   
    37.                             Thread.sleep(100);//休息下   
    38.                         }catch(InterruptedException e){e.printStackTrace();}   
    39.                     }   
    40.                 }   
    41.             };   
    42.             queue.add(task);   
    43.         }   
    44.     }   
    45.     //開始干活   
    46.     public void startWork(){   
    47.         helotPool.prestartAllCoreThreads();   
    48.     }   
    49.     public static void main(String[] args) {   
    50.         HelotPoolTest pool = new HelotPoolTest();   
    51.         pool.assignTask();   
    52.         pool.startWork();   
    53.     }   
    54. }  

     程序啟動,用Jprofiler監控,剛啟動時會有5名奴隸干活不一會就會有線程退出,最后5個線程全部退,報警器對每個線程退出都能記錄到導致線程退出的原因。標準的Executor實現是:

    在需求不高時回收空閑的線程,在需求增加時添加新的線程,如果任務拋出了異常,就會用一個全新的工作線程取代出錯的那個。

    JDK文檔是這么說的,不過通過Jprofiler監控只有在5名奴隸全部逃跑,沒人干活的時候ThreadPoolExecutor才會生成一個新線程繼續搬石頭,并不是只要一個線程退出就會馬上生成新線程去代替。



    Author: orangelizq
    email: orangelizq@163.com

    歡迎大家訪問我的個人網站 萌萌的IT人
    posted on 2013-05-29 16:43 桔子汁 閱讀(600) 評論(0)  編輯  收藏 所屬分類: J2SE
    主站蜘蛛池模板: 精品国产亚洲一区二区在线观看| 成年人在线免费观看| 亚洲偷自拍拍综合网| 理论片在线观看免费| 亚洲国产成人精品久久久国产成人一区二区三区综 | 亚洲国产精品热久久| 大地资源在线资源免费观看 | 亚洲影院在线观看| 免费国产黄网站在线观看可以下载| 亚洲精品国产精品乱码不99 | 一区二区三区在线观看免费| 亚洲国产精品成人久久蜜臀 | 亚洲国产中文在线二区三区免| 麻豆国产精品免费视频| 国产精品亚洲自在线播放页码| 免费毛片在线看片免费丝瓜视频| 亚洲欧美日韩综合俺去了| 亚洲国产精品自在拍在线播放| 欧洲乱码伦视频免费国产| 国产亚洲av人片在线观看| 精品一区二区三区无码免费视频| 亚洲经典在线中文字幕| 最近中文字幕免费mv视频8| 美女被免费网站在线视频免费 | 国产国产人免费视频成69大陆| 色爽黄1000部免费软件下载| 亚洲成色WWW久久网站| 亚洲成年人免费网站| 国产精品无码亚洲一区二区三区| 在线观看亚洲成人| 亚洲一区二区三区免费在线观看| 亚洲欧洲av综合色无码| 国产亚洲精品久久久久秋霞| 五月婷婷综合免费| 人人爽人人爽人人片A免费 | 手机看片久久国产免费| 二区久久国产乱子伦免费精品| 亚洲国产亚洲片在线观看播放| 亚洲国产成人VA在线观看| 亚洲w码欧洲s码免费 | 久久不见久久见免费视频7|