999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

基于Qt的線程池服務(wù)器的研究與應(yīng)用

2014-01-01 03:10:00張衛(wèi)強(qiáng)
無線電通信技術(shù) 2014年6期
關(guān)鍵詞:方法

劉 飛,張衛(wèi)強(qiáng),羅 彤

(寧波大學(xué)信息科學(xué)與工程學(xué)院,浙江寧波315211)

0 引言

傳統(tǒng)的網(wǎng)絡(luò)服務(wù)器模型中,服務(wù)器收到一個(gè)客戶端請求后,創(chuàng)建一個(gè)新線程,由該線程執(zhí)行任務(wù),任務(wù)完成后,線程退出,即“即時(shí)創(chuàng)建,即時(shí)刪除”,對服務(wù)器來說創(chuàng)建線程已經(jīng)比創(chuàng)建進(jìn)程節(jié)約了不少時(shí)間,但是如果大量的客戶端對服務(wù)器過于頻繁的進(jìn)行連接,該服務(wù)器就將在創(chuàng)建和刪除線程的過程中耗費(fèi)大量時(shí)間[1]。所以減少創(chuàng)建和銷毀對象,尤其是減少很耗資源的對象成為提高服務(wù)程序效率的重要手段之一。線程池是一組預(yù)先創(chuàng)建的線程,快速、容易地處理收到的業(yè)務(wù)。比起傳統(tǒng)的“即時(shí)創(chuàng)建,即時(shí)刪除”的模型,該類型服務(wù)器節(jié)省了創(chuàng)建和回收線程的開銷,響應(yīng)更快,效率更高[2]。

為高圖形用戶界面的響應(yīng)速度,Qt提供豐富的多線程編程支持[],而為減少Q(mào)t創(chuàng)建和刪除線程的開銷,Qt又提供了線程池技術(shù)的支持。為降低基于Qt的網(wǎng)絡(luò)服務(wù)器頻繁的創(chuàng)建線程的開銷,本文就Qt線程池技術(shù)進(jìn)行分析,研究其運(yùn)行機(jī)制,并運(yùn)用該技術(shù)創(chuàng)建一個(gè)服務(wù)器模型。

1 Qt的線程池類和QTcpServer類

Qt提供了與平臺無關(guān)的線程類,在Qt系統(tǒng)中與線程池相關(guān)的最重要的類是QThreadPool和QRunnable。QThreadPool用于管理一批線程,它負(fù)責(zé)管理和回收單個(gè)線程[4]。每個(gè) Qt應(yīng)用可通過QThreadPool::globalInstance()獲得一個(gè)全局的QThreadPool對象。QRunable類表示一個(gè)任務(wù)或者一段被執(zhí)行代碼的一個(gè)接口。使用QThreadPool類來運(yùn)行一個(gè)QRunnable對象。把一個(gè)QRunnable放入了QThreadPool的運(yùn)行隊(duì)列中,只要線程是可見的,QRunnable將會被拾起并且在那個(gè)線程里運(yùn)行,QRunnable是一種輕量級的、以“run and forget”方式來在另一個(gè)線程開啟任務(wù)的抽象類,為了實(shí)現(xiàn)這一功能,要做的全部事情是派生QRunnable類,并實(shí)現(xiàn)純虛函數(shù)方法 run()[5]。

QTcpServer類不是QAbstractSocket抽象套接字類,而是繼承于QObject基類,為編寫TCP客戶端和服務(wù)器應(yīng)用程序提供一個(gè) TCP基礎(chǔ)服務(wù)類[6]。QTcpSocket類提供了基于TCP協(xié)議的通用接口,為監(jiān)聽每一個(gè)客戶端的連接,可通過調(diào)用listen()函數(shù)來實(shí)現(xiàn),每當(dāng)服務(wù)器收到一個(gè)客戶端的連接請求時(shí)就會發(fā)射newConnection()信號,如果要接受待處理的連接,則可通過調(diào)用nextPendingConnection()函數(shù),并返回一個(gè)連接的 QTcpSocket()套接字[7],該套接字作為服務(wù)端的一個(gè)子對象,可以通過使用這個(gè)返回的套接字和客戶端進(jìn)行連接,這就意味著當(dāng)QTcpServer對象要銷毀時(shí),該套接字也會隨之被自動刪除,即不能在其他線程中使用該套接字,如果想在其他線程中繼續(xù)使用該套接字,那么需要重載void incomingConnection(int socketDescriptor)函數(shù),這個(gè)函數(shù)將新創(chuàng)建一個(gè)QTcpSocket套接字,該函數(shù)中socketDescriptor參數(shù)是新連接的套接字描述符,然后在一個(gè)整形的待連接鏈表中將套接字存儲,最后發(fā)射信號newConnection()。

2 線程池機(jī)制

2.1 線程池技術(shù)介紹

線程池就是在進(jìn)程中先創(chuàng)建好一批線程,當(dāng)有任務(wù)到來時(shí),就從創(chuàng)建好的線程中取出一個(gè)線程來處理該任務(wù),任務(wù)結(jié)束之后,將線程置為空閑,放回線程池中繼續(xù)等待下次任務(wù)的到來[8],工作過程如圖1所示。

2.2 基于Qt的線程池機(jī)制

在Qt中通過globalInstance()方法,每個(gè) Qt的應(yīng)用程序都可獲得一個(gè)全局的QThreadPool對象。

theInstance()函數(shù)功能通過Q_GLOBAL_STATIC(QThreadPool,theInstance)宏實(shí)現(xiàn),以此返回一個(gè)全局的QThreadPool對象。此外由于QThreadPool類繼承QObject,在QThreadPool類中可以使用Qt提供的信號與槽機(jī)制。圖1為線程池工作原理。

圖1 線程池工作原理

通過上面介紹的函數(shù)就可以得到一個(gè)全局的QthreadPool,但是為了能夠調(diào)用該線程池中的一個(gè)線程,還需要提供繼承于QRunnable的一個(gè)類,從而實(shí)現(xiàn)其中的run方法。然后創(chuàng)建一個(gè)該類的對象,傳遞給void QThreadPool::Start(QRunnable*runnable,int priority),該函數(shù)具體實(shí)現(xiàn)如下所示。

該方法通過Q_D宏獲取QThreadPool命名為d的數(shù)據(jù)結(jié)構(gòu),真正開始QThreadPool一個(gè)線程是通過enqueueTask()方法實(shí)現(xiàn)的。

enqueueTask()方法將runnable放入隊(duì)列中來管理,并喚醒QThreadPool管理的線程池中的一個(gè)線程實(shí)現(xiàn)一個(gè)繼承QRunnable類的run方法。

在默認(rèn)情況下,QthreadPool將能夠自動刪除創(chuàng)建的 QRunnable對象。使用 void QRunnable::setAutoDelete(bool autoDelete)方法可以改變這一默認(rèn)行為,但是該標(biāo)志必須在調(diào)用QThreadPool::Start()之前被設(shè)置,否則將會出現(xiàn)錯誤。

QThreadPool支持在QRunnable::run方法中通過調(diào)用tryStart(this)來多次執(zhí)行相同的QRunnable。當(dāng)最后一個(gè)線程退出run函數(shù)后,如果autoDelete啟用的話,將刪除QRunnable對象。在autoDelete啟用的情況下,調(diào)用start()方法多次執(zhí)行同一QRunnable會產(chǎn)生競態(tài),因此要避免這樣做。

通過void setExpiryTimeout(int expiryTimeout)函數(shù)來設(shè)置線程的過期時(shí)間,默認(rèn)過期時(shí)間為30 s。如果設(shè)置expriyTimeout為一個(gè)負(fù)數(shù),則代表禁止使用超時(shí)機(jī)制。如果要規(guī)定最大的線程數(shù)可通set-MaxThreadCount(int maxThreadCount)來設(shè)置,其參數(shù)maxThreadCount為要設(shè)置的數(shù)量,通過 void maxThreadCount()可以查詢可使用的最大線程數(shù)。為了確保該線程被釋放后可循環(huán)使用,可以通過函數(shù)void releaseThread()釋放該線程的,以便它可以被再次使用。

3 Qt線程池服務(wù)器模型的建立

在下面的步驟中,將利用線程池技術(shù)創(chuàng)建一個(gè)服務(wù)器模型,以此介紹線程池的創(chuàng)建步驟,并通過命令客戶端對創(chuàng)建的服務(wù)器進(jìn)行測試。

3.1 主要相關(guān)代碼

首先創(chuàng)建一個(gè)繼承QTcpServer的一個(gè)類,在該類的實(shí)現(xiàn)方法中監(jiān)聽客戶端的連接每當(dāng)有客戶端連接時(shí)都會調(diào)用virtual void incomingConnection(int socketDescriptor)函數(shù)[9,10],因此處理這個(gè)請求的過程就可以在這個(gè)函數(shù)中實(shí)現(xiàn),對一個(gè)線程池的服務(wù)器,每當(dāng)客戶端試圖連接的時(shí)候,服務(wù)器從線程池中啟動一個(gè)線程,負(fù)責(zé)對這個(gè)客戶端進(jìn)行服務(wù),所以,incomingConnection()這個(gè)函數(shù)所要做的就是建立一個(gè)線程,進(jìn)而對客戶端進(jìn)行服務(wù)。代碼如下,先添加類的前置聲明:

在myserver.cpp文件中,首先在構(gòu)造函數(shù)中通過globalInstance()函數(shù)獲取一個(gè)全局QThreadPool對象,并設(shè)置最大線程數(shù)為20,之后實(shí)現(xiàn)監(jiān)聽客戶端連接。

該服務(wù)器監(jiān)聽到客戶端試圖建立一個(gè)套接字連接,該套接字將自動分配一個(gè) SocketDescriptor標(biāo)識,該標(biāo)識會在服務(wù)器連接中使用,應(yīng)當(dāng)提供給每一個(gè)線程。

服務(wù)器在監(jiān)聽到客戶端試圖建立socket連接時(shí),會為此socket分配一個(gè)標(biāo)識socketDescriptor,該標(biāo)識在建立服務(wù)器連接時(shí)使用,所以應(yīng)提供給每一個(gè)線程。接下來派生QRunnable類,并實(shí)現(xiàn)純虛函數(shù)run()。

3.2 程序運(yùn)行測試

在Linux環(huán)境下編譯運(yùn)行服務(wù)器程序結(jié)果如圖2所示。

圖2 編譯運(yùn)行

此時(shí),如圖2所示服務(wù)器已經(jīng)啟動,下面用Linux命令終端的telnet程序模擬一個(gè)客戶端,在telnet程序中輸入命令:open 127.0.0.1 1234(此處的127.0.01為程序中的設(shè)置的IP地址,即IPV4的本地主機(jī)地址,端口號是1234),請求服務(wù)器進(jìn)行連接,并對其進(jìn)行測試,測試結(jié)果如圖3、圖4所示。

圖3 客戶端

圖4 服務(wù)器端

通過以上步驟,利用線程池技術(shù)完成了一個(gè)服務(wù)器的創(chuàng)建,即使用 QThreadPool類來運(yùn)行一個(gè)QRunnable對象,它維護(hù)了一個(gè)線程池。當(dāng)客戶端請求連接時(shí),服務(wù)器端調(diào)用已經(jīng)創(chuàng)建好的線程池中的一個(gè)線程對該客戶端請求進(jìn)行處理,如圖3所示,服務(wù)器將一個(gè)簡單的字符串“Hello world!!”傳遞給客戶端,并在命令客戶端顯示,此時(shí)服務(wù)器端打印出為該客戶端服務(wù)的線程ID,如圖4所示。通過以上測試,運(yùn)用線程池技術(shù)實(shí)現(xiàn)了服務(wù)器與客戶端之間的通信。

4 結(jié)束語

針對目前多線程服務(wù)器在接受客戶端頻繁連接會增加開銷這一弱點(diǎn),提出利用Qt線程池技術(shù)減少程序中頻繁創(chuàng)建線程的開銷的優(yōu)勢,在服務(wù)器模型中加入線程池技術(shù)的支持,即利用QThreadPool線程池來管理一組線程,每當(dāng)有客戶端連接時(shí),就有單個(gè)線程對象來處理客戶端請求并交由該線程池管理和回收,從而減少了服務(wù)器頻繁創(chuàng)建線程的開銷,提高服務(wù)器工作效率。但是由于QRunnable并非QObject類,它沒有一個(gè)內(nèi)置的與其他組件顯式通訊的方法,必須使用底層的線程原語(比如收集結(jié)構(gòu)的枷鎖保護(hù)隊(duì)列等)來親自編寫代碼。

[1] 曾云.基于ARM+QT平臺的嵌入式賓館客服系統(tǒng)軟件設(shè)計(jì)[D].上海:東華大學(xué),2011:25-31.

[2] 劉新強(qiáng),曾兵義.用線程池解決服務(wù)器并發(fā)請求的方案設(shè)計(jì)[J].現(xiàn)代電子技術(shù),2011,34(15):141 -143.

[3] 黃宇東,胡躍明,陳安.基于Qt的多線程技術(shù)應(yīng)用于研究[J].軟件導(dǎo)刊,2009,8(10):40-42.

[4] 趙祖龍.基于Qt/Embedded的嵌入式跨平臺聊天系統(tǒng)設(shè)計(jì)[J].信息技術(shù),2010,34(12):144 -147.

[5] 蔡志明,盧傳富,李立夏.精通Qt4編程[M].北京:電子工業(yè)出版社,2008.

[6] 崔弘珂.一種空間環(huán)境下的TCP傳輸技術(shù)研究[J].無線電通信技術(shù),2011,37(4):21-24.

[7] 丁林松,黃麗琴.Qt4圖形設(shè)計(jì)與嵌入式開發(fā)[M].北京:人民郵電出版社,2009.

[8] 汪成林.linux環(huán)境下基于SSL的安全文件傳輸系統(tǒng)研究[D].杭州:浙江工業(yè)大學(xué),2012:38-45.

[9] 馮艷紅,何加銘,楊任爾,等.基于Android藍(lán)牙技術(shù)的健康服務(wù)系統(tǒng)設(shè)計(jì)[J].無線電通信技術(shù),2014,40(1):61-64.85-88.

[10]馬睿.基于Qt的TCP網(wǎng)絡(luò)編程研究與應(yīng)用[J].福建電腦,2010,26(11):138 -139.

猜你喜歡
方法
中醫(yī)特有的急救方法
中老年保健(2021年9期)2021-08-24 03:52:04
高中數(shù)學(xué)教學(xué)改革的方法
化學(xué)反應(yīng)多變幻 “虛擬”方法幫大忙
變快的方法
兒童繪本(2020年5期)2020-04-07 17:46:30
學(xué)習(xí)方法
用對方法才能瘦
Coco薇(2016年2期)2016-03-22 02:42:52
最有效的簡單方法
山東青年(2016年1期)2016-02-28 14:25:23
四大方法 教你不再“坐以待病”!
Coco薇(2015年1期)2015-08-13 02:47:34
賺錢方法
捕魚
主站蜘蛛池模板: 1024国产在线| 久久久久无码精品国产免费| 久青草国产高清在线视频| 国产在线拍偷自揄拍精品| 国产欧美视频综合二区| 欧美成人午夜影院| 精品综合久久久久久97超人| 18禁高潮出水呻吟娇喘蜜芽| 国产白丝av| 国产欧美视频综合二区| 国产经典免费播放视频| 久久香蕉国产线看观看式| 人人看人人鲁狠狠高清| 国产精品香蕉在线观看不卡| 国产视频久久久久| 亚洲AⅤ综合在线欧美一区| 国产欧美日韩另类精彩视频| 亚洲日韩精品无码专区| 国产福利在线观看精品| 国产欧美自拍视频| 日韩欧美中文| 无码免费视频| 亚洲av色吊丝无码| 美女高潮全身流白浆福利区| 亚洲人成高清| 国产黄色爱视频| 尤物国产在线| 国产AV无码专区亚洲A∨毛片| 福利姬国产精品一区在线| 欧美一级高清片欧美国产欧美| 国产不卡在线看| 国产自产视频一区二区三区| 日韩精品成人在线| 97久久精品人人做人人爽| AV不卡在线永久免费观看| 亚洲视频a| 亚洲成人精品在线| 午夜国产理论| 欧美午夜视频| 亚洲国产看片基地久久1024| 国产精品极品美女自在线| 国产精品七七在线播放| 国产美女免费| 日韩福利视频导航| 丰满少妇αⅴ无码区| 久草视频精品| 亚洲天堂高清| 欧美国产在线一区| 青青极品在线| 97久久精品人人| 精品视频一区二区三区在线播| 999精品在线视频| 九九这里只有精品视频| 婷婷久久综合九色综合88| 亚洲二三区| a毛片免费在线观看| 日韩二区三区| 激情国产精品一区| 国产成人精品2021欧美日韩| 国产美女视频黄a视频全免费网站| 在线永久免费观看的毛片| 国产精品无码翘臀在线看纯欲| 欧美日韩精品一区二区在线线| 四虎永久在线精品国产免费| 欧美成人午夜视频| 国产一区在线观看无码| 日韩精品亚洲一区中文字幕| 色综合久久久久8天国| 一级毛片不卡片免费观看| 婷婷中文在线| 好吊色妇女免费视频免费| 国产精品亚洲а∨天堂免下载| 精品丝袜美腿国产一区| 久久这里只有精品8| 亚洲色图在线观看| 中国一级毛片免费观看| 国产福利小视频高清在线观看| 2020极品精品国产| 亚洲三级视频在线观看| 国产黄色视频综合| 亚洲日韩高清在线亚洲专区| 亚洲一区二区三区香蕉|