我們先關(guān)注一下這個(gè)類的構(gòu)造函數(shù),然后再看它的process()方法。第16-24行是它的構(gòu)造函數(shù),首先它給ThreadPoolManager類的成員變量maxThread賦值,maxThread表示用于控制線程池中最大線程的數(shù)量。第18行初始化一個(gè)數(shù)組vector,它用來存放所有的SimpleThread類,這時(shí)候就充分體現(xiàn)了JAVA語言的優(yōu)越性與藝術(shù)性:如果你用C語言的話,至少要寫100行以上的代碼來完成vector的功能,而且C語言數(shù)組只能容納類型統(tǒng)一的基本數(shù)據(jù)類型,無法容納對(duì)象。好了,閑話少說,第19-24行的循環(huán)完成這樣一個(gè)功能:先創(chuàng)建一個(gè)新的SimpleThread類,然后將它放入vector中去,最后用thread.start()來啟動(dòng)這個(gè)線程,為什么要用start()方法來啟動(dòng)線程呢?因?yàn)檫@是JAVA語言中所規(guī)定的,如果你不用的話,那這些線程將永遠(yuǎn)得不到激活,從而導(dǎo)致本示例程序根本無法運(yùn)行。 下面我們?cè)賮砜匆幌聀rocess()方法,第30-40行的循環(huán)依次從vector數(shù)組中選取SimpleThread線程,并檢查它是否處于激活狀態(tài)(所謂激活狀態(tài)是指此線程是否正在處理客戶端的請(qǐng)求),如果處于激活狀態(tài)的話,那繼續(xù)查找vector數(shù)組的下一項(xiàng),如果vector數(shù)組中所有的線程都處于激活狀態(tài)的話,那它會(huì)打印出一條信息,提示用戶稍候再試。相反如果找到了一個(gè)睡眠線程的話,那第35-38行會(huì)對(duì)此進(jìn)行處理,它先告訴客戶端是哪一個(gè)線程來處理這個(gè)請(qǐng)求,然后將客戶端的請(qǐng)求,即字符串a(chǎn)rgument轉(zhuǎn)發(fā)給SimpleThread類的setArgument()方法進(jìn)行處理,并調(diào)用SimpleThread類的setRunning()方法來喚醒當(dāng)前線程,來對(duì)客戶端請(qǐng)求進(jìn)行處理。
可能你還對(duì)setRunning()方法是怎樣喚醒線程的有些不明白,那我們現(xiàn)在就進(jìn)入最后一個(gè)類:SimpleThread類,它的源代碼如下:
用戶在run()接口中寫入自己的應(yīng)用處理邏輯。那么怎么來控制線程的睡眠與喚醒呢?其實(shí)很簡(jiǎn)單,JAVA語言為所有的對(duì)象都內(nèi)置了wait()和notify()方法,當(dāng)一個(gè)線程調(diào)用wait()方法時(shí),則線程進(jìn)入睡眠狀態(tài),就像停在了當(dāng)前代碼上了,也不會(huì)繼續(xù)執(zhí)行它以下的代碼了,當(dāng)調(diào)用notify()方法時(shí),則會(huì)從調(diào)用wait()方法的那行代碼繼續(xù)執(zhí)行以下的代碼,這個(gè)過程有點(diǎn)像編譯器中的斷點(diǎn)調(diào)試的概念。以本程序?yàn)槔?8行調(diào)用了wait()方法,則這個(gè)線程就像凝固了一樣停在了38行上了,如果在第13行進(jìn)行一個(gè)notify()調(diào)用的話,那線程會(huì)從第38行上喚醒,繼續(xù)從第39行開始執(zhí)行以下的代碼了。
通過以上的講述,現(xiàn)在就不難理解SimpleThread類了,第9-14行通過設(shè)置一個(gè)標(biāo)志runningFlag激活當(dāng)前線程,第25-29行是SimpleThread類的構(gòu)造函數(shù),它用來告訴客戶端啟動(dòng)的是第幾號(hào)進(jìn)程。第31-50行則是我實(shí)現(xiàn)的run()接口,它實(shí)際上是一個(gè)無限循環(huán),在循環(huán)中首先判斷一下標(biāo)志runningFlag,如果沒有runningFlag為false的話,那線程處理睡眠狀態(tài),否則第42-45行會(huì)進(jìn)行真正的處理:先打印用戶鍵入的字符串,然后睡眠5秒鐘,為什么要睡眠5秒鐘呢?如果你不加上這句代碼的話,由于計(jì)算機(jī)處理速度遠(yuǎn)遠(yuǎn)超過你的鍵盤輸入速度,因此你看到的總是第1號(hào)線程來處理你的請(qǐng)求,從而達(dá)不到演示效果。最后第45行調(diào)用setRunning()方法又將線程置于睡眠狀態(tài),等待新請(qǐng)求的到來。
最后還有一點(diǎn)要注意的是,如果在一個(gè)方法中調(diào)用了wait()和notify()函數(shù),那一定要將此方法置為同步的,即synchronized,否則在編譯時(shí)會(huì)報(bào)錯(cuò),并得到一個(gè)莫名其妙的消息:“current thread not owner”(當(dāng)前線程不是擁有者)。
Copyright myfavorite.