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

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

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

    拾貝殼

    走過的路
    隨筆 - 39, 文章 - 1, 評論 - 14, 引用 - 0
    數據加載中……

    一個簡單的ThreadPool分析

    一個簡單的ThreadPool
    ? 原文來自http://www.informit.com/articles/printerfriendly.asp?p=30483&r1=1&rl=1
    ? 項目是多線程的,所以引入了線程池這個東西。池子是個老美寫的。在項目中表現的還不錯。所以把它摘出來,介紹給以后或許需要用到它的同行們。
    ? 關于為什么要采用ThreadPool,原文已經提到了:創建一個線程是需要開銷的;如果線程數量過大的話,cpu就會浪費很大的精力做線程切換。
    ? ThreadPool的實現過程就是對WorkerThread的同步和通信的管理過程。
    ? 我們來看代碼。
    ? 首先,在ThreadPool構造的時候,創建10個WorkerThread(size=10)并讓他們運行。每個WorkerThread線程都有個ThreadPool的引用,用于查詢ThreadPool的狀態和獲得同步鎖.WorkerThread運行以后,循環調用ThreadPool的方法進行查詢,如果沒有發現任務,ThreadPool告訴正在查詢的線程進入休眠狀態,WorkerThread釋放對查詢方法的鎖定.這樣在還沒有任務的時候,所有的10個WorkerThread都會進入休眠狀態,進入等待ThreadPool對象的等待鎖定池,只有ThreadPool對象發出notify方法(或notifyAll)后WorkerThread線程才進入對象鎖定池準備獲得對象鎖進入運行狀態。
    代碼片斷:
    while ( !assignments.iterator().hasNext() )
    ??? wait();
    如果你有jprofile或者其他的觀察線程的工具,你可以看到有10個線程都在休眠狀態.
    ? 接著,我們向ThreadPool中加入任務,這些任務都實現了Runnable的run方法.(至于為什么把任務都做成Runnable,譯者至今也有些疑問?預定俗成?TimerTask也是實現自Runnable,弄得初學者經常把真正運行的線程搞混).ThreadPool每assign一個任務,就會發出一條消息,通知它的等待鎖定池中的線程.各個線程以搶占的方式獲得對象鎖,然后很順利的獲得一條任務.并把此任務從ThreadPool里面刪除.沒有搶到的繼續等待.
    Runnable r = (Runnable)assignments.iterator().next();
    ?? assignments.remove(r);
    WorkerThread從ThreadPool那里獲得了任務,繼續向下執行。
    target = owner.getAssignment();
    ?? if (target!=null) {
    ??? target.run();?????
    ??? owner.done.workerEnd();
    ?? }
    記住,這里調用的是target.run();而不是調用的線程的start()方法。也就是說在這里表現出的WorkerThread和task之間的關系僅僅是簡單的方法調用的關系,并沒有額外產生新線程。(這就是我上面納悶為什么大家都實現Runnable來做task的原因)
    ?大家可能注意到,WorkerThread并沒有對異常作處理。而我們知道發生在線程上的異常會導致線程死亡。解決的辦法有2中,一種是通過threadpool的管理來重新激起一個線程,一種是把異常在線程之內消滅。在項目中,我采用的是第二中,因此這個片斷改稱這樣:
    if (target!=null) {
    ? try{
    ??? target.run();?????
    ?? }
    ? catch(Throwable t){
    ?.......
    ?? }
    ??? owner.done.workerEnd();
    }
    在WorkerThread完成一個task以后,繼續循環作同樣的流程.
    在這個ThreadPool的實現里面,Jeff Heaton用了一個Done類來觀察WorkerThread的執行情況.和ThreadPoool的等待鎖定池不同,Done的等待鎖定池里面放的是初始化ThreadPool的線程(可能是你的主線程),我們叫他母線程.
    ? 在給出的測試例子中.母線程在調用complete()方法后進入休眠(在監視中等待),一開始是waitBegin()讓他休眠,在assign加入task以后,waitDone()方法讓他休眠.在WorkerThread完成一個task以后,通知waitDone()起來重新檢查activeThreads的數值.若不為0,繼續睡覺.若為0,那么母線程走完,死亡(這個時候該做的task已經做完了).母線程走完,ThreadPool還存在嗎?答案是存在,因為WorkerThread還沒有消亡,他們在等待下一批任務,他們有ThreadPool的引用,保證ThreadPool依然存在.大家或許已經明白Done這個類的作用了.
    ? 細心的讀者或許會發現,發生在Done實例上的notify()并不是像ThreadPool上的notify()那樣每次都能完成一項工作.比如除了第一個被assign的task,其他的task在assign進去的時候,發出的notify()對于waitDone()來說是句"狼來了".
    ?最后在ThreadPool需要被清理得時候,使每一個WorkerThread中斷(這個時候或許所有的WorkerThread都在休眠)并銷毀.記住這里也是一個異步的過程.等到每一個WorkerThread都已經銷毀,finalize()的方法體走完.ThreadPool被銷毀.
    ?for (int i=0;i<threads.length;i++) {
    ?? threads[i].interrupt();
    ?? done.workerBegin();
    ?? threads[i].destroy();
    ? }
    ? done.waitDone();
    為什么有句done.workerBegin();?不明白.
    參考文章:
    http://www.zdnet.com.cn/developer/common/printfriend/printfriendly.htm?AT=39276905-3800066897t-20000560c

    posted on 2006-07-16 20:07 binge 閱讀(7188) 評論(1)  編輯  收藏 所屬分類: J2SE

    評論

    # re: 一個簡單的ThreadPool分析  回復  更多評論   

    糾正一個明顯的錯誤:

    ----------
    關于為什么要采用ThreadPool,原文已經提到了:創建一個線程是需要開銷的,如果線程數量過大的話,cpu就會浪費很大的精力做線程切換。
    ----------

    線程池的目的不是reuse,而是overload shield.這是初涉多線程編程的人經常會犯的概念性錯誤,也是對于線程池功能最常見的誤解

    況且,你指出的原文已經說的很明白了,你似乎沒有理解原文的意思
    原文:
    Why a Thread Pool?
    When programming the crawler in the previous section, a problem that would soon present itself is the number of threads to use. A crawler may have to visit tens of thousands of pages, and you certainly do not want to create tens of thousands of threads because each thread imposes a certain amount of overhead. If the number of threads grows too large, the computer will be spending all of its time switching between threads, rather than just executing them.

    To solve this problem, you must create a thread pool. The thread pool is given some fixed number of threads to use. The thread pool will assign its tasks to each of these threads. As the threads finish with old tasks, new ones are assigned. This causes the program to use a fixed number of threads, not to be continually creating new threads.

    -----------------

    再說,這篇文章太老了,說java沒有提供內建的線程池實現,java5.0已經提供了內建的線程池
    2006-07-18 02:59 | fisher
    主站蜘蛛池模板: 91精品导航在线网址免费| 男女一进一出抽搐免费视频| 午夜理伦剧场免费| 国产亚洲成归v人片在线观看| 羞羞漫画页面免费入口欢迎你| 免费a级毛片无码av| 亚洲高清毛片一区二区| 性一交一乱一视频免费看| 亚洲人成人伊人成综合网无码| 日韩在线天堂免费观看| 亚洲色大成WWW亚洲女子| 成人爱做日本视频免费| MM1313亚洲精品无码久久| 亚洲国产中文字幕在线观看 | 亚洲男人电影天堂| 久久国产乱子伦免费精品| 亚洲欧洲精品一区二区三区| 成年人网站免费视频| 亚洲国产精品免费观看| 国产一级一片免费播放| 一级中文字幕乱码免费| 亚洲va无码专区国产乱码| 色欲A∨无码蜜臀AV免费播| 亚洲剧场午夜在线观看| 男女啪啪永久免费观看网站| 人妻18毛片a级毛片免费看| 亚洲日本va在线视频观看| 日本黄网站动漫视频免费| 在线观看亚洲AV日韩A∨| 亚洲国产综合精品中文字幕| 国产在线一区二区综合免费视频| 亚洲精品美女久久久久| 免费国产美女爽到喷出水来视频| 三级网站免费观看| 亚洲国产成a人v在线观看| 亚洲精品和日本精品| 30岁的女人韩剧免费观看| 风间由美在线亚洲一区| 亚洲成AV人片在线观看| 免费无码黄网站在线观看| 国产在线观a免费观看|