国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
線程池的介紹及簡(jiǎn)單實(shí)現(xiàn)

2002 年 8 月 22 日

服務(wù)器程序利用線程技術(shù)響應(yīng)客戶請(qǐng)求已經(jīng)司空見(jiàn)慣,可能您認(rèn)為這樣做效率已經(jīng)很高,但您有沒(méi)有想過(guò)優(yōu)化一下使用線程的方法。該文章將向您介紹服務(wù)器程序如何利用線程池來(lái)優(yōu)化性能并提供一個(gè)簡(jiǎn)單的線程池實(shí)現(xiàn)。

線程池的技術(shù)背景

在面向?qū)ο缶幊讨?,?chuàng)建和銷毀對(duì)象是很費(fèi)時(shí)間的,因?yàn)閯?chuàng)建一個(gè)對(duì)象要獲取內(nèi)存資源或者其它更多資源。在Java中更是如此,虛 擬機(jī)將試圖跟蹤每一個(gè)對(duì)象,以便能夠在對(duì)象銷毀后進(jìn)行垃圾回收。所以提高服務(wù)程序效率的一個(gè)手段就是盡可能減少創(chuàng)建和銷毀對(duì)象的次數(shù),特別是一些很耗資源 的對(duì)象創(chuàng)建和銷毀。如何利用已有對(duì)象來(lái)服務(wù)就是一個(gè)需要解決的關(guān)鍵問(wèn)題,其實(shí)這就是一些"池化資源"技術(shù)產(chǎn)生的原因。比如大家所熟悉的數(shù)據(jù)庫(kù)連接池正是遵 循這一思想而產(chǎn)生的,本文將介紹的線程池技術(shù)同樣符合這一思想。

目前,一些著名的大公司都特別看好這項(xiàng)技術(shù),并早已經(jīng)在他們的產(chǎn)品中應(yīng)用該技術(shù)。比如IBM的WebSphere,IONA的 Orbix 2000在SUN的 Jini中,Microsoft的MTS(Microsoft Transaction Server 2.0),COM+等。

現(xiàn)在您是否也想在服務(wù)器程序應(yīng)用該項(xiàng)技術(shù)?







線程池技術(shù)如何提高服務(wù)器程序的性能

我所提到服務(wù)器程序是指能夠接受客戶請(qǐng)求并能處理請(qǐng)求的程序,而不只是指那些接受網(wǎng)絡(luò)客戶請(qǐng)求的網(wǎng)絡(luò)服務(wù)器程序。

多線程技術(shù)主要解決處理器單元內(nèi)多個(gè)線程執(zhí)行的問(wèn)題,它可以顯著減少處理器單元的閑置時(shí)間,增加處理器單元的吞吐能力。但如果對(duì)多線程應(yīng)用不當(dāng),會(huì)增加對(duì)單個(gè)任務(wù)的處理時(shí)間。可以舉一個(gè)簡(jiǎn)單的例子:

假設(shè)在一臺(tái)服務(wù)器完成一項(xiàng)任務(wù)的時(shí)間為T

     T1 創(chuàng)建線程的時(shí)間            T2 在線程中執(zhí)行任務(wù)的時(shí)間,包括線程間同步所需時(shí)間            T3 線程銷毀的時(shí)間		

顯然T = T1+T2+T3。注意這是一個(gè)極度簡(jiǎn)化的假設(shè)。

可以看出T1,T3是多線程本身的帶來(lái)的開(kāi)銷,我們渴望減少T1,T3所用的時(shí)間,從而減少T的時(shí)間。但一些線程的使用者并沒(méi)有注意到 這一點(diǎn),所以在程序中頻繁的創(chuàng)建或銷毀線程,這導(dǎo)致T1和T3在T中占有相當(dāng)比例。顯然這是突出了線程的弱點(diǎn)(T1,T3),而不是優(yōu)點(diǎn)(并發(fā)性)。

線程池技術(shù)正是關(guān)注如何縮短或調(diào)整T1,T3時(shí)間的技術(shù),從而提高服務(wù)器程序性能的。它把T1,T3分別安排在服務(wù)器程序的啟動(dòng)和結(jié)束的時(shí)間段或者一些空閑的時(shí)間段,這樣在服務(wù)器程序處理客戶請(qǐng)求時(shí),不會(huì)有T1,T3的開(kāi)銷了。

線程池不僅調(diào)整T1,T3產(chǎn)生的時(shí)間段,而且它還顯著減少了創(chuàng)建線程的數(shù)目。在看一個(gè)例子:

假設(shè)一個(gè)服務(wù)器一天要處理50000個(gè)請(qǐng)求,并且每個(gè)請(qǐng)求需要一個(gè)單獨(dú)的線程完成。我們比較利用線程池技術(shù)和不利于線程池技術(shù)的服務(wù)器 處理這些請(qǐng)求時(shí)所產(chǎn)生的線程總數(shù)。在線程池中,線程數(shù)一般是固定的,所以產(chǎn)生線程總數(shù)不會(huì)超過(guò)線程池中線程的數(shù)目或者上限(以下簡(jiǎn)稱線程池尺寸),而如果 服務(wù)器不利用線程池來(lái)處理這些請(qǐng)求則線程總數(shù)為50000。一般線程池尺寸是遠(yuǎn)小于50000。所以利用線程池的服務(wù)器程序不會(huì)為了創(chuàng)建50000而在處 理請(qǐng)求時(shí)浪費(fèi)時(shí)間,從而提高效率。

這些都是假設(shè),不能充分說(shuō)明問(wèn)題,下面我將討論線程池的簡(jiǎn)單實(shí)現(xiàn)并對(duì)該程序進(jìn)行對(duì)比測(cè)試,以說(shuō)明線程技術(shù)優(yōu)點(diǎn)及應(yīng)用領(lǐng)域。







線程池的簡(jiǎn)單實(shí)現(xiàn)及對(duì)比測(cè)試

一般一個(gè)簡(jiǎn)單線程池至少包含下列組成部分。

  1. 線程池管理器(ThreadPoolManager):用于創(chuàng)建并管理線程池
  2. 工作線程(WorkThread): 線程池中線程
  3. 任務(wù)接口(Task):每個(gè)任務(wù)必須實(shí)現(xiàn)的接口,以供工作線程調(diào)度任務(wù)的執(zhí)行。
  4. 任務(wù)隊(duì)列:用于存放沒(méi)有處理的任務(wù)。提供一種緩沖機(jī)制。

線程池管理器至少有下列功能:創(chuàng)建線程池,銷毀線程池,添加新任務(wù) 創(chuàng)建線程池的部分代碼如下:

  …                        //create threads                        synchronized(workThreadVector)                        {                        for(int j = 0; j < i; j++)                        {                        threadNum++;                        WorkThread workThread = new WorkThread(taskVector, threadNum);                        workThreadVector.addElement(workThread);                        }                        }                        …                        

注意同步workThreadVector并沒(méi)有降低效率,相反提高了效率,請(qǐng)參考Brian Goetz的文章。 銷毀線程池的部分代碼如下:

  …                        while(!workThreadVector.isEmpty())                        {                        if(debugLevel > 2)                        System.out.println("stop:"+(i));                        i++;                        try                        {                        WorkThread workThread = (WorkThread)workThreadVector.remove(0);                        workThread.closeThread();                        continue;                        }                        catch(Exception exception)                        {                        if(debugLevel > 2)                        exception.printStackTrace();                        }                        break;                        }                        …                        

添加新任務(wù)的部分代碼如下:

   …                        synchronized(taskVector)                        {                        taskVector.addElement(taskObj);                        taskVector.notifyAll();                        }                        …                        

工作線程是一個(gè)可以循環(huán)執(zhí)行任務(wù)的線程,在沒(méi)有任務(wù)時(shí)將等待。由于代碼比較多在此不羅列.

任務(wù)接口是為所有任務(wù)提供統(tǒng)一的接口,以便工作線程處理。任務(wù)接口主要規(guī)定了任務(wù)的入口,任務(wù)執(zhí)行完后的收尾工作,任務(wù)的執(zhí)行狀態(tài)等。在文章結(jié)尾有相關(guān)代碼的下載。

以上所描述的線程池結(jié)構(gòu)很簡(jiǎn)單,一些復(fù)雜的線程池結(jié)構(gòu)將不再此討論。

在下載代碼中有測(cè)試驅(qū)動(dòng)程序(TestThreadPool),我利用這個(gè)測(cè)試程序的輸出數(shù)據(jù)統(tǒng)計(jì)出下列測(cè)試結(jié)果。測(cè)試有兩個(gè)參數(shù)要設(shè)置:

  1. 線程池中線程數(shù),即線程池尺寸。
  2. 要完成的任務(wù)數(shù)。

分別將一個(gè)參數(shù)固定,另一個(gè)參數(shù)變動(dòng)以考察兩個(gè)參數(shù)所產(chǎn)生的不同結(jié)果。所用測(cè)試機(jī)器分別為普通PC機(jī)(Win2000 JDK1.3.1)和SUN服務(wù)器(Solaris Unix JDK1.3.1),機(jī)器配置在此不便指明。

表1:測(cè)試數(shù)據(jù)及對(duì)應(yīng)結(jié)果

線程池尺寸 任務(wù)數(shù) 沒(méi)有應(yīng)用線程池所用的時(shí)間(單位:毫秒,OS:win) 應(yīng)用線程池所用的時(shí)間(單位:毫秒,OS:win) 沒(méi)有應(yīng)用線程池所用的時(shí)間(單位:毫秒,OS:Solaris) 應(yīng)用線程池所用的時(shí)間(單位:毫秒,OS:Solaris)
1 5000 3896 130 6513 327
2 5000 3455 151 6221 659
4 5000 3425 120 5448 433
8 5000 3475 160 5769 1478
16 5000 3505 211 5785 1970
32 5000 3455 251 6403 875
64 5000 3595 501 5182 1103
128 5000 3515 881 5154 405
256 5000 3495 3104 5502 1589
512 5000 3425 5488 5667 1262
16 1 20 0 22 3
16 2 20 20 21 13
16 4 20 10 27 10
16 8 20 20 22 24
16 16 30 20 29 48
16 32 40 20 46 108
16 64 60 20 72 199
16 128 110 20 148 335
16 256 201 20 252 132
16 512 411 40 522 382
16 1024 811 71 1233 610
16 2048 1552 80 2045 135
16 4096 2874 250 4828 787

圖1.線程池的尺寸的對(duì)服務(wù)器程序的性能影響

根據(jù)以上統(tǒng)計(jì)數(shù)據(jù)可得出下圖:


圖2.任務(wù)數(shù)對(duì)服務(wù)器程序的沖擊

數(shù)據(jù)分析如下:

圖1是改變線程池尺寸對(duì)服務(wù)器性能的影響,在該測(cè)試過(guò)程中,服務(wù)器的要完成的任務(wù)數(shù)固定為為5000。從圖1中可以看出合理配置線程池 尺寸對(duì)于大量任務(wù)處理的效率有非常明顯的提高,但是一旦尺寸選擇不合理(過(guò)大或過(guò)小)就會(huì)嚴(yán)重降低影響服務(wù)器性能。理論上"過(guò)小"將出現(xiàn)任務(wù)不能及時(shí)處理 的情況,但在圖表中顯示出某些小尺寸的線程池表現(xiàn)很好,這是因?yàn)闇y(cè)試驅(qū)動(dòng)中有很多線程同步開(kāi)銷,且這個(gè)開(kāi)銷相對(duì)于完成單個(gè)任務(wù)的時(shí)間是不能忽略的。"過(guò) 大"則會(huì)出現(xiàn)線程間同步開(kāi)銷太大的問(wèn)題,而且在線程間切換很耗CPU時(shí)間,在圖表顯示的很清楚??梢?jiàn)任何一個(gè)好技術(shù),如果濫用都會(huì)造成災(zāi)難性后果。

圖2是用不同數(shù)量的任務(wù)來(lái)沖擊服務(wù)器程序,在該測(cè)試過(guò)程中,服務(wù)器線程池尺寸固定為16。可以看出線程池在處理少量任務(wù)時(shí)的優(yōu)勢(shì)不明 顯。所以線程池技術(shù)有一定的適應(yīng)范圍,關(guān)于適用范圍將在后面討論。但對(duì)于大量的任務(wù)的處理,線程池的優(yōu)勢(shì)表現(xiàn)非常卓越,服務(wù)器程序處理請(qǐng)求的時(shí)間雖然有波 動(dòng),但是其平均值相對(duì)小多了。

值得注意的是測(cè)試方案中,統(tǒng)計(jì)任務(wù)的完成時(shí)間沒(méi)有包含了創(chuàng)建線程池的時(shí)間。在實(shí)際線程池工作時(shí),即利用線程池處理任務(wù)時(shí),創(chuàng)建線程池的時(shí)間是不必計(jì)算在內(nèi)的。

由于測(cè)試驅(qū)動(dòng)程序有很多同步代碼,特別是等待線程執(zhí)行完畢的同步(代碼中為sleepToWait(long l)方法的調(diào)用),這些代碼降低了代碼執(zhí)行效率,這是測(cè)試驅(qū)動(dòng)一個(gè)缺點(diǎn),但這個(gè)測(cè)試驅(qū)動(dòng)可以說(shuō)明線程池相對(duì)于簡(jiǎn)單使用線程的優(yōu)勢(shì)。







關(guān)于高級(jí)線程池的探討

簡(jiǎn)單線程池存在一些問(wèn)題,比如如果有大量的客戶要求服務(wù)器為其服務(wù),但由于線程池的工作線程是有限的,服務(wù)器只能為部分客戶服 務(wù),其它客戶提交的任務(wù),只能在任務(wù)隊(duì)列中等待處理。一些系統(tǒng)設(shè)計(jì)人員可能會(huì)不滿這種狀況,因?yàn)樗麄儗?duì)服務(wù)器程序的響應(yīng)時(shí)間要求比較嚴(yán)格,所以在系統(tǒng)設(shè)計(jì) 時(shí)可能會(huì)懷疑線程池技術(shù)的可行性,但是線程池有相應(yīng)的解決方案。調(diào)整優(yōu)化線程池尺寸是高級(jí)線程池要解決的一個(gè)問(wèn)題。主要有下列解決方案:

方案一:動(dòng)態(tài)增加工作線程

在一些高級(jí)線程池中一般提供一個(gè)可以動(dòng)態(tài)改變的工作線程數(shù)目的功能,以適應(yīng)突發(fā)性的請(qǐng)求。一旦請(qǐng)求變少了將逐步減少線程池中工 作線程的數(shù)目。當(dāng)然線程增加可以采用一種超前方式,即批量增加一批工作線程,而不是來(lái)一個(gè)請(qǐng)求才建立創(chuàng)建一個(gè)線程。批量創(chuàng)建是更加有效的方式。該方案還有 應(yīng)該限制線程池中工作線程數(shù)目的上限和下限。否則這種靈活的方式也就變成一種錯(cuò)誤的方式或者災(zāi)難,因?yàn)轭l繁的創(chuàng)建線程或者短時(shí)間內(nèi)產(chǎn)生大量的線程將會(huì)背離 使用線程池原始初衷--減少創(chuàng)建線程的次數(shù)。

舉例:Jini中的TaskManager,就是一個(gè)精巧線程池管理器,它是動(dòng)態(tài)增加工作線程的。SQL Server采用單進(jìn)程(Single Process)多線程(Multi-Thread)的系統(tǒng)結(jié)構(gòu),1024個(gè)數(shù)量的線程池,動(dòng)態(tài)線程分配,理論上限32767。

方案二:優(yōu)化工作線程數(shù)目

如果不想在線程池應(yīng)用復(fù)雜的策略來(lái)保證工作線程數(shù)滿足應(yīng)用的要求,你就要根據(jù)統(tǒng)計(jì)學(xué)的原理來(lái)統(tǒng)計(jì)客戶的請(qǐng)求數(shù)目,比如高峰時(shí)段 平均一秒鐘內(nèi)有多少任務(wù)要求處理,并根據(jù)系統(tǒng)的承受能力及客戶的忍受能力來(lái)平衡估計(jì)一個(gè)合理的線程池尺寸。線程池的尺寸確實(shí)很難確定,所以有時(shí)干脆用經(jīng)驗(yàn) 值。

舉例:在MTS中線程池的尺寸固定為100。

方案三:一個(gè)服務(wù)器提供多個(gè)線程池

在一些復(fù)雜的系統(tǒng)結(jié)構(gòu)會(huì)采用這個(gè)方案。這樣可以根據(jù)不同任務(wù)或者任務(wù)優(yōu)先級(jí)來(lái)采用不同線程池處理。

舉例:COM+用到了多個(gè)線程池。

這三種方案各有優(yōu)缺點(diǎn)。在不同應(yīng)用中可能采用不同的方案或者干脆組合這三種方案來(lái)解決實(shí)際問(wèn)題。






線程池技術(shù)適用范圍及應(yīng)注意的問(wèn)題

下面是我總結(jié)的一些線程池應(yīng)用范圍,可能是不全面的。

線程池的應(yīng)用范圍:

  1. 需要大量的線程來(lái)完成任務(wù),且完成任務(wù)的時(shí)間比較短。 WEB服務(wù)器完成網(wǎng)頁(yè)請(qǐng)求這樣的任務(wù),使用線程池技術(shù)是非常合適的。因?yàn)閱蝹€(gè)任務(wù)小,而任務(wù)數(shù)量巨大,你可以想象一個(gè)熱門網(wǎng)站的點(diǎn)擊次數(shù)。 但對(duì)于長(zhǎng)時(shí)間的任務(wù),比如一個(gè)Telnet連接請(qǐng)求,線程池的優(yōu)點(diǎn)就不明顯了。因?yàn)門elnet會(huì)話時(shí)間比線程的創(chuàng)建時(shí)間大多了。
  2. 對(duì)性能要求苛刻的應(yīng)用,比如要求服務(wù)器迅速相應(yīng)客戶請(qǐng)求。
  3. 接受突發(fā)性的大量請(qǐng)求,但不至于使服務(wù)器因此產(chǎn)生大量線程的應(yīng)用。突發(fā)性大量客戶請(qǐng)求,在沒(méi)有線程池情況下,將產(chǎn)生大量線程,雖然理論上大部分操作系統(tǒng)線程數(shù)目最大值不是問(wèn)題,短時(shí)間內(nèi)產(chǎn)生大量線程可能使內(nèi)存到達(dá)極限,并出現(xiàn)"OutOfMemory"的錯(cuò)誤。






結(jié)束語(yǔ)

本文只是簡(jiǎn)單介紹線程池技術(shù)。可以看出線程池技術(shù)對(duì)于服務(wù)器程序的性能改善是顯著的。線程池技術(shù)在服務(wù)器領(lǐng)域有著廣泛的應(yīng)用前景。希望這項(xiàng)技術(shù)能夠應(yīng)用到您的多線程服務(wù)程序中。



參考資料

Danny Ayers 等:Professional Java Server Programming

Tarak Modi: Why Thread Pools are Important in Java

Brett Spell :Professional java Programming

Jini(TM) v1.2.1代碼

Brian Goetz 的 Java 理論和實(shí)踐專欄

Microsoft Knowledge Base Article :Q282490



關(guān)于作者


幸勇 一位軟件設(shè)計(jì)開(kāi)發(fā)者。愛(ài)好廣泛。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
線程池的原理及實(shí)現(xiàn)
高性能服務(wù)器架構(gòu)思路【不僅是思路】
一個(gè)非常簡(jiǎn)單,非常短小的線程池
C#多線程與UI響應(yīng)
輕量級(jí)線程池的實(shí)現(xiàn)
quartz詳解4:quartz線程管理
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服