田素貞,王應(yīng)戰(zhàn)
(商丘職業(yè)技術(shù)學(xué)院計(jì)算機(jī)系,河南商丘476000)
開(kāi)發(fā)數(shù)據(jù)庫(kù)軟件最頻繁的操作是與數(shù)據(jù)庫(kù)服務(wù)器進(jìn)行交互。對(duì)于少量的數(shù)據(jù),我們可以利用單線程順序執(zhí)行,但是對(duì)于大批量的數(shù)據(jù),單線程順序與多個(gè)數(shù)據(jù)庫(kù)進(jìn)行交互,將無(wú)法及時(shí)響應(yīng)用戶操作,用戶體驗(yàn)非常不好。
在制造業(yè)中,工廠對(duì)于一種產(chǎn)品至少有幾十萬(wàn)條數(shù)據(jù),而且工廠會(huì)不斷生產(chǎn)出新的產(chǎn)品,這樣會(huì)增加大量的數(shù)據(jù)。如果把所有的數(shù)據(jù)都放在一個(gè)數(shù)據(jù)庫(kù)中,必將會(huì)增加數(shù)據(jù)庫(kù)服務(wù)器的負(fù)擔(dān)。為了今后軟件的升級(jí)及可維護(hù)性,可以將不同產(chǎn)品的數(shù)據(jù)放在不同主機(jī)上。那么,當(dāng)用戶發(fā)出請(qǐng)求時(shí),如何從分布在不同主機(jī)上的數(shù)據(jù)庫(kù)快速獲得結(jié)果,得到快速的響應(yīng)?
本文在實(shí)際應(yīng)用中,利用.NET平臺(tái),通過(guò)多線程技術(shù),實(shí)現(xiàn)同時(shí)對(duì)多個(gè)數(shù)據(jù)庫(kù)進(jìn)行交互,提高數(shù)據(jù)庫(kù)訪問(wèn)效率,優(yōu)化用戶交互,取得了較好的效果。
首先介紹進(jìn)程及線程。
進(jìn)程是具有一定功能的程序,是關(guān)于一個(gè)數(shù)據(jù)集合的一次執(zhí)行過(guò)程,進(jìn)程包括運(yùn)行中的程序和程序所使用到的內(nèi)存和系統(tǒng)資源。[1]
線程(Thread)是系統(tǒng)可調(diào)度的基本單位,是一組指令的集合,它可以在程序里獨(dú)立執(zhí)行,線程是輕量級(jí)的進(jìn)程,通常由操作系統(tǒng)負(fù)責(zé)多個(gè)線程的調(diào)度和執(zhí)行。
一個(gè)進(jìn)程可以包含多個(gè)線程,線程是程序中的一個(gè)執(zhí)行流,每個(gè)線程都有自己的專有寄存器(棧指針、程序計(jì)數(shù)器等),但代碼區(qū)是共享的,所以它們可以同時(shí)執(zhí)行進(jìn)程地址空間中的程序代碼。[2]操作系統(tǒng)為每個(gè)獨(dú)立的線程安排一些CPU時(shí)間,以輪轉(zhuǎn)方式向線程提供時(shí)間片,這樣,雖然實(shí)際上在同一時(shí)間只有一個(gè)線程在運(yùn)行,但是由于時(shí)間片很小,從而使得每個(gè)線程看起來(lái)好像都在同時(shí)運(yùn)行一樣。
多線程程序設(shè)計(jì),就是使單個(gè)程序包含多個(gè)線程,并且使得多個(gè)線程能夠并發(fā)執(zhí)行,完成多項(xiàng)任務(wù),以提高系統(tǒng)的效率。[3]當(dāng)多線程程序執(zhí)行時(shí),該程序?qū)?yīng)的進(jìn)程中有多個(gè)控制流同時(shí)運(yùn)行。與并發(fā)多進(jìn)程程序設(shè)計(jì)不同的是,多線程程序設(shè)計(jì)是在一個(gè)進(jìn)程中包含并發(fā)執(zhí)行的多個(gè)控制流,并不是把多個(gè)控制流一一分散在多個(gè)進(jìn)程中。
多個(gè)線程共享同一個(gè)進(jìn)程的地址空間,使得線程創(chuàng)建,線程之間的切換及通信的開(kāi)銷大大降低,可以顯著減少處理器單元的閑置時(shí)間,增加處理器單元的吞吐能力,但是如果使用不當(dāng),會(huì)增加對(duì)單個(gè)任務(wù)的處理時(shí)間。[4]
線程池是后臺(tái)執(zhí)行多任務(wù)線程的集合,它為每一個(gè)傳入的請(qǐng)求分配一個(gè)線程,不占用主線程,也不延遲后續(xù)請(qǐng)求處理,從而實(shí)現(xiàn)異步處理請(qǐng)求。當(dāng)所有線程都繁忙時(shí),將額外的任務(wù)放在任務(wù)隊(duì)列中,當(dāng)有空閑線程時(shí)執(zhí)行。當(dāng)池中的某個(gè)線程完成任務(wù)后,它將返回到等待線程隊(duì)列中,等待再次被使用,這種重用可以不需要為每個(gè)請(qǐng)求創(chuàng)建和銷毀線程,從而減少系統(tǒng)開(kāi)銷。[5]
.NET框架為每一個(gè)進(jìn)程提供了一個(gè)線程池,使應(yīng)用程序能夠根據(jù)需要來(lái)有效地利用多個(gè)線程。[6]一個(gè)線程監(jiān)視排到線程池的若干個(gè)等待操作的狀態(tài)。當(dāng)一個(gè)等待操作完成時(shí),線程池中的一個(gè)輔助線程就會(huì)執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。線程池中的線程由系統(tǒng)進(jìn)行管理。.NET框架的重要組成部分CLR(Common Language Runtime,通用語(yǔ)言運(yùn)行時(shí)間)內(nèi)置支持多線程應(yīng)用,可以通過(guò)System Threading命名空間提供支持多線程編程的類和接口。
System Threading ThreadPool類實(shí)現(xiàn)了線程池,由于每個(gè)進(jìn)程只有一個(gè)線程池,不能創(chuàng)建新的,這個(gè)類中所有成員都是靜態(tài)的,沒(méi)有公開(kāi)的構(gòu)造函數(shù)。這樣可以把所有的異步編程技術(shù)都集中到同個(gè)池中。[7]線程池中的線程數(shù)目?jī)H受可用內(nèi)存的限制。但是,線程池將對(duì)允許在進(jìn)程中同時(shí)處于活動(dòng)狀態(tài)的線程數(shù)目強(qiáng)制實(shí)施限制(這取決于CPU的數(shù)目和其他因素)。默認(rèn)情況下,每個(gè)系統(tǒng)處理器最多可以運(yùn)行25個(gè)線程池線程。即使是在所有線程都處于空閑狀態(tài)時(shí),線程池也會(huì)維持最小的可用線程數(shù),以便隊(duì)列任務(wù)可以立即啟動(dòng)。將終止超過(guò)此最小數(shù)目的空閑線程,以節(jié)省系統(tǒng)資源。一般情況下,每個(gè)處理器要維持一個(gè)空閑線程。[8]
線程池的執(zhí)行原理如圖1。啟動(dòng)進(jìn)程,此時(shí)線程池并沒(méi)有創(chuàng)建。將回調(diào)方法排入隊(duì)列(比如調(diào)用Thread Pool Queue User Work Item方法)時(shí)創(chuàng)建線程池,一個(gè)線程監(jiān)視所有已排隊(duì)到線程池中的任務(wù),將所有要執(zhí)行的任務(wù)插入到任務(wù)隊(duì)列中,如果有空閑線程就調(diào)用執(zhí)行,否則,就將額外任務(wù)插入到任務(wù)隊(duì)列,等待有空閑線程時(shí)調(diào)用執(zhí)行。如圖3所示。
在制造業(yè)中,每一類產(chǎn)品都會(huì)有很多的數(shù)據(jù),并且數(shù)據(jù)隨著時(shí)間及產(chǎn)品種類的增多而激增。把所有數(shù)據(jù)僅僅放在一個(gè)數(shù)據(jù)庫(kù)中,這對(duì)數(shù)據(jù)庫(kù)服務(wù)器本身的性能提出很高的要求。與數(shù)據(jù)庫(kù)交互可能會(huì)成為提高軟件性能的瓶頸。面對(duì)大量的數(shù)據(jù),可以把它們按照產(chǎn)品種類分別存儲(chǔ)在不同的機(jī)器上,這樣可以降低對(duì)數(shù)據(jù)庫(kù)服務(wù)器性能的要求,也為今后難以預(yù)料的數(shù)據(jù)劇增提供方便。但是,如何及時(shí)地從分布在不同機(jī)器上的數(shù)據(jù)庫(kù)中取出數(shù)據(jù),獲得良好的用戶交互成為軟件開(kāi)發(fā)人員普遍關(guān)注的問(wèn)題。


按照傳統(tǒng)的編程方法,為了使客戶端的請(qǐng)求得到滿足,服務(wù)器端應(yīng)用系統(tǒng)必須依次訪問(wèn)多個(gè)數(shù)據(jù)庫(kù),如圖1所求。對(duì)于擁有大批量數(shù)據(jù)的制造工業(yè),這樣訪問(wèn)數(shù)據(jù)庫(kù)會(huì)花費(fèi)大量的時(shí)間,用戶將會(huì)等待相當(dāng)長(zhǎng)的時(shí)間,這樣用戶體驗(yàn)非常不好。

圖3 多線程并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)示意圖
如果采用多線程程序設(shè)計(jì),程序性能會(huì)有很大的提高。如圖2所示,客戶端發(fā)出請(qǐng)求,比如向數(shù)據(jù)庫(kù)中插入數(shù)據(jù),服務(wù)器收到請(qǐng)求后,啟動(dòng)進(jìn)程,創(chuàng)建線程池,將每個(gè)任務(wù)插入到任務(wù)中,并分配線程池線程,每個(gè)線程池線程可以同時(shí)訪問(wèn)數(shù)據(jù)庫(kù)。與多個(gè)數(shù)據(jù)庫(kù)同時(shí)交互,并將交互成功的消息返回客戶端。程序把占據(jù)長(zhǎng)時(shí)間的數(shù)據(jù)庫(kù)交互放到后臺(tái)去處理,充分利用CPU資源,有效縮短用戶等待時(shí)間。
配置所有測(cè)試都是在處理器為奔騰?D 2.6 GHz、內(nèi)存為1 GB的計(jì)算機(jī)上進(jìn)行的,數(shù)據(jù)庫(kù)為Oracle 9i。操作系統(tǒng)為Microsoft Windows XP Professional SP2*,所有代碼都是在Microsoft Visual Studio.NET 2005*環(huán)境下開(kāi)發(fā)。本試驗(yàn)具體內(nèi)容是向三個(gè)數(shù)據(jù)庫(kù)中分別插入1000條數(shù)據(jù)。三個(gè)數(shù)據(jù)庫(kù)分別放在不同的機(jī)器上。
由表1可以明顯看出,利用多線程并行執(zhí)行多任務(wù),效率要比串行執(zhí)行高。

表1 實(shí)驗(yàn)結(jié)果
基于.NET平臺(tái),利用多線程技術(shù),與分布在不同機(jī)器上的數(shù)據(jù)庫(kù)同時(shí)交互,通過(guò)測(cè)試,發(fā)現(xiàn)多線程技術(shù)可以顯著提高服務(wù)器程序性能,提高系統(tǒng)性能。
[1]Jim Beveridge,Robert Wiener.Win32 多線程程序設(shè)計(jì)[M].侯捷,譯.武漢:華中科技大學(xué)出版社,2002.
[2]歐廣宇,鄧桂英.多線程技術(shù)基于 VB.NET的實(shí)現(xiàn)[J].微機(jī)發(fā)展,2004(11):50-53.
[3]楊沙洲,楊學(xué)軍.多處理機(jī)系統(tǒng)線程環(huán)境[J].計(jì)算機(jī)工程與科學(xué),2005(5):94-96.
[4]胡燕翔,孟晗.多進(jìn)程下子程序綜合方法研究[J].計(jì)算機(jī)工程,2006(15):49-51.
[5]趙海,李志蜀,韓學(xué)為,等.線程池的優(yōu)化設(shè)計(jì)[J].四川大學(xué)學(xué)報(bào):自然科學(xué)版,2005(1):68-72.
[6]王金保,李偉.用VB.Net創(chuàng)建多線程及同步的幾個(gè)問(wèn)題[J].撫順石油學(xué)院學(xué)報(bào),2003(3):65 -68.
[7]李雙權(quán).一種Java多線程可達(dá)性測(cè)試框架系統(tǒng)的研究和實(shí)現(xiàn)[D].暨南大學(xué),2003.
[8]周炎濤.Windows中的多線程編程技術(shù)和實(shí)現(xiàn)[J].計(jì)算技術(shù)與自動(dòng)化,2002(3):112-119.