田素貞,王應(yīng)戰(zhàn)
(商丘職業(yè)技術(shù)學(xué)院計算機(jī)系,河南商丘476000)
開發(fā)數(shù)據(jù)庫軟件最頻繁的操作是與數(shù)據(jù)庫服務(wù)器進(jìn)行交互。對于少量的數(shù)據(jù),我們可以利用單線程順序執(zhí)行,但是對于大批量的數(shù)據(jù),單線程順序與多個數(shù)據(jù)庫進(jìn)行交互,將無法及時響應(yīng)用戶操作,用戶體驗(yàn)非常不好。
在制造業(yè)中,工廠對于一種產(chǎn)品至少有幾十萬條數(shù)據(jù),而且工廠會不斷生產(chǎn)出新的產(chǎn)品,這樣會增加大量的數(shù)據(jù)。如果把所有的數(shù)據(jù)都放在一個數(shù)據(jù)庫中,必將會增加數(shù)據(jù)庫服務(wù)器的負(fù)擔(dān)。為了今后軟件的升級及可維護(hù)性,可以將不同產(chǎn)品的數(shù)據(jù)放在不同主機(jī)上。那么,當(dāng)用戶發(fā)出請求時,如何從分布在不同主機(jī)上的數(shù)據(jù)庫快速獲得結(jié)果,得到快速的響應(yīng)?
本文在實(shí)際應(yīng)用中,利用.NET平臺,通過多線程技術(shù),實(shí)現(xiàn)同時對多個數(shù)據(jù)庫進(jìn)行交互,提高數(shù)據(jù)庫訪問效率,優(yōu)化用戶交互,取得了較好的效果。
首先介紹進(jìn)程及線程。
進(jìn)程是具有一定功能的程序,是關(guān)于一個數(shù)據(jù)集合的一次執(zhí)行過程,進(jìn)程包括運(yùn)行中的程序和程序所使用到的內(nèi)存和系統(tǒng)資源。[1]
線程(Thread)是系統(tǒng)可調(diào)度的基本單位,是一組指令的集合,它可以在程序里獨(dú)立執(zhí)行,線程是輕量級的進(jìn)程,通常由操作系統(tǒng)負(fù)責(zé)多個線程的調(diào)度和執(zhí)行。
一個進(jìn)程可以包含多個線程,線程是程序中的一個執(zhí)行流,每個線程都有自己的專有寄存器(棧指針、程序計數(shù)器等),但代碼區(qū)是共享的,所以它們可以同時執(zhí)行進(jìn)程地址空間中的程序代碼。[2]操作系統(tǒng)為每個獨(dú)立的線程安排一些CPU時間,以輪轉(zhuǎn)方式向線程提供時間片,這樣,雖然實(shí)際上在同一時間只有一個線程在運(yùn)行,但是由于時間片很小,從而使得每個線程看起來好像都在同時運(yùn)行一樣。
多線程程序設(shè)計,就是使單個程序包含多個線程,并且使得多個線程能夠并發(fā)執(zhí)行,完成多項(xiàng)任務(wù),以提高系統(tǒng)的效率。[3]當(dāng)多線程程序執(zhí)行時,該程序?qū)?yīng)的進(jìn)程中有多個控制流同時運(yùn)行。與并發(fā)多進(jìn)程程序設(shè)計不同的是,多線程程序設(shè)計是在一個進(jìn)程中包含并發(fā)執(zhí)行的多個控制流,并不是把多個控制流一一分散在多個進(jìn)程中。
多個線程共享同一個進(jìn)程的地址空間,使得線程創(chuàng)建,線程之間的切換及通信的開銷大大降低,可以顯著減少處理器單元的閑置時間,增加處理器單元的吞吐能力,但是如果使用不當(dāng),會增加對單個任務(wù)的處理時間。[4]
線程池是后臺執(zhí)行多任務(wù)線程的集合,它為每一個傳入的請求分配一個線程,不占用主線程,也不延遲后續(xù)請求處理,從而實(shí)現(xiàn)異步處理請求。當(dāng)所有線程都繁忙時,將額外的任務(wù)放在任務(wù)隊(duì)列中,當(dāng)有空閑線程時執(zhí)行。當(dāng)池中的某個線程完成任務(wù)后,它將返回到等待線程隊(duì)列中,等待再次被使用,這種重用可以不需要為每個請求創(chuàng)建和銷毀線程,從而減少系統(tǒng)開銷。[5]
.NET框架為每一個進(jìn)程提供了一個線程池,使應(yīng)用程序能夠根據(jù)需要來有效地利用多個線程。[6]一個線程監(jiān)視排到線程池的若干個等待操作的狀態(tài)。當(dāng)一個等待操作完成時,線程池中的一個輔助線程就會執(zhí)行對應(yīng)的回調(diào)函數(shù)。線程池中的線程由系統(tǒng)進(jìn)行管理。.NET框架的重要組成部分CLR(Common Language Runtime,通用語言運(yùn)行時間)內(nèi)置支持多線程應(yīng)用,可以通過System Threading命名空間提供支持多線程編程的類和接口。
System Threading ThreadPool類實(shí)現(xiàn)了線程池,由于每個進(jìn)程只有一個線程池,不能創(chuàng)建新的,這個類中所有成員都是靜態(tài)的,沒有公開的構(gòu)造函數(shù)。這樣可以把所有的異步編程技術(shù)都集中到同個池中。[7]線程池中的線程數(shù)目僅受可用內(nèi)存的限制。但是,線程池將對允許在進(jìn)程中同時處于活動狀態(tài)的線程數(shù)目強(qiáng)制實(shí)施限制(這取決于CPU的數(shù)目和其他因素)。默認(rèn)情況下,每個系統(tǒng)處理器最多可以運(yùn)行25個線程池線程。即使是在所有線程都處于空閑狀態(tài)時,線程池也會維持最小的可用線程數(shù),以便隊(duì)列任務(wù)可以立即啟動。將終止超過此最小數(shù)目的空閑線程,以節(jié)省系統(tǒng)資源。一般情況下,每個處理器要維持一個空閑線程。[8]
線程池的執(zhí)行原理如圖1。啟動進(jìn)程,此時線程池并沒有創(chuàng)建。將回調(diào)方法排入隊(duì)列(比如調(diào)用Thread Pool Queue User Work Item方法)時創(chuàng)建線程池,一個線程監(jiān)視所有已排隊(duì)到線程池中的任務(wù),將所有要執(zhí)行的任務(wù)插入到任務(wù)隊(duì)列中,如果有空閑線程就調(diào)用執(zhí)行,否則,就將額外任務(wù)插入到任務(wù)隊(duì)列,等待有空閑線程時調(diào)用執(zhí)行。如圖3所示。
在制造業(yè)中,每一類產(chǎn)品都會有很多的數(shù)據(jù),并且數(shù)據(jù)隨著時間及產(chǎn)品種類的增多而激增。把所有數(shù)據(jù)僅僅放在一個數(shù)據(jù)庫中,這對數(shù)據(jù)庫服務(wù)器本身的性能提出很高的要求。與數(shù)據(jù)庫交互可能會成為提高軟件性能的瓶頸。面對大量的數(shù)據(jù),可以把它們按照產(chǎn)品種類分別存儲在不同的機(jī)器上,這樣可以降低對數(shù)據(jù)庫服務(wù)器性能的要求,也為今后難以預(yù)料的數(shù)據(jù)劇增提供方便。但是,如何及時地從分布在不同機(jī)器上的數(shù)據(jù)庫中取出數(shù)據(jù),獲得良好的用戶交互成為軟件開發(fā)人員普遍關(guān)注的問題。
按照傳統(tǒng)的編程方法,為了使客戶端的請求得到滿足,服務(wù)器端應(yīng)用系統(tǒng)必須依次訪問多個數(shù)據(jù)庫,如圖1所求。對于擁有大批量數(shù)據(jù)的制造工業(yè),這樣訪問數(shù)據(jù)庫會花費(fèi)大量的時間,用戶將會等待相當(dāng)長的時間,這樣用戶體驗(yàn)非常不好。
圖3 多線程并發(fā)訪問數(shù)據(jù)庫示意圖
如果采用多線程程序設(shè)計,程序性能會有很大的提高。如圖2所示,客戶端發(fā)出請求,比如向數(shù)據(jù)庫中插入數(shù)據(jù),服務(wù)器收到請求后,啟動進(jìn)程,創(chuàng)建線程池,將每個任務(wù)插入到任務(wù)中,并分配線程池線程,每個線程池線程可以同時訪問數(shù)據(jù)庫。與多個數(shù)據(jù)庫同時交互,并將交互成功的消息返回客戶端。程序把占據(jù)長時間的數(shù)據(jù)庫交互放到后臺去處理,充分利用CPU資源,有效縮短用戶等待時間。
配置所有測試都是在處理器為奔騰?D 2.6 GHz、內(nèi)存為1 GB的計算機(jī)上進(jìn)行的,數(shù)據(jù)庫為Oracle 9i。操作系統(tǒng)為Microsoft Windows XP Professional SP2*,所有代碼都是在Microsoft Visual Studio.NET 2005*環(huán)境下開發(fā)。本試驗(yàn)具體內(nèi)容是向三個數(shù)據(jù)庫中分別插入1000條數(shù)據(jù)。三個數(shù)據(jù)庫分別放在不同的機(jī)器上。
由表1可以明顯看出,利用多線程并行執(zhí)行多任務(wù),效率要比串行執(zhí)行高。
表1 實(shí)驗(yàn)結(jié)果
基于.NET平臺,利用多線程技術(shù),與分布在不同機(jī)器上的數(shù)據(jù)庫同時交互,通過測試,發(fā)現(xiàn)多線程技術(shù)可以顯著提高服務(wù)器程序性能,提高系統(tǒng)性能。
[1]Jim Beveridge,Robert Wiener.Win32 多線程程序設(shè)計[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ī)工程與科學(xué),2005(5):94-96.
[4]胡燕翔,孟晗.多進(jìn)程下子程序綜合方法研究[J].計算機(jī)工程,2006(15):49-51.
[5]趙海,李志蜀,韓學(xué)為,等.線程池的優(yōu)化設(shè)計[J].四川大學(xué)學(xué)報:自然科學(xué)版,2005(1):68-72.
[6]王金保,李偉.用VB.Net創(chuàng)建多線程及同步的幾個問題[J].撫順石油學(xué)院學(xué)報,2003(3):65 -68.
[7]李雙權(quán).一種Java多線程可達(dá)性測試框架系統(tǒng)的研究和實(shí)現(xiàn)[D].暨南大學(xué),2003.
[8]周炎濤.Windows中的多線程編程技術(shù)和實(shí)現(xiàn)[J].計算技術(shù)與自動化,2002(3):112-119.