2017最新有關(guān)線(xiàn)程池介紹論文
線(xiàn)程池是Mysql5.6的一個(gè)核心功能,對于服務(wù)器應用而言,無(wú)論是web應用服務(wù)還是DB服務(wù),高并發(fā)請求始終是一個(gè)繞不開(kāi)的話(huà)題。當有大量請求并發(fā)訪(fǎng)問(wèn)時(shí),一定伴隨著(zhù)資源的不斷創(chuàng )建和釋放,導致資源利用率低,降低了服務(wù)質(zhì)量。線(xiàn)程池是一種通用的技術(shù),通過(guò)預先創(chuàng )建一定數量的線(xiàn)程,當有請求達到時(shí),線(xiàn)程池分配一個(gè)線(xiàn)程提供服務(wù),請求結束后,該線(xiàn)程又去服務(wù)其他請求。 通過(guò)這種方式,避免了線(xiàn)程和內存對象的頻繁創(chuàng )建和釋放,降低了服務(wù)端的并發(fā)度,減少了上下文切換和資源的競爭,提高資源利用效率。所有服務(wù)的線(xiàn)程池本質(zhì)都是位了提高資源利用效率,并且實(shí)現方式也大體相同。本文主要說(shuō)明Mysql線(xiàn)程池的實(shí)現原理。
在Mysql5.6出現以前,Mysql處理連接的方式是One-Connection-Per-Thread,即對于每一個(gè)數據庫連接,Mysql-Server都會(huì )創(chuàng )建一個(gè)獨立的線(xiàn)程服務(wù),請求結束后,銷(xiāo)毀線(xiàn)程。再來(lái)一個(gè)連接請求,則再創(chuàng )建一個(gè)連接,結束后再進(jìn)行銷(xiāo)毀。這種方式在高并發(fā)情況下,會(huì )導致線(xiàn)程的頻繁創(chuàng )建和釋放。當然,通過(guò)thread-cache,我們可以將線(xiàn)程緩存起來(lái),以供下次使用,避免頻繁創(chuàng )建和釋放的問(wèn)題,但是無(wú)法解決高連接數的問(wèn)題。One-Connection-Per-Thread方式隨著(zhù)連接數暴增,導致需要創(chuàng )建同樣多的服務(wù)線(xiàn)程,高并發(fā)線(xiàn)程意味著(zhù)高的內存消耗,更多的上下文切換(cpu cache命中率降低)以及更多的資源競爭,導致服務(wù)出現抖動(dòng)。相對于One-Thread-Per-Connection方式,一個(gè)線(xiàn)程對應一個(gè)連接,Thread-Pool實(shí)現方式中,線(xiàn)程處理的最小單位是statement(語(yǔ)句),一個(gè)線(xiàn)程可以處理多個(gè)連接的請求。這樣,在保證充分利用硬件資源情況下(合理設置線(xiàn)程池大小),可以避免瞬間連接數暴增導致的服務(wù)器抖動(dòng)。
調度方式實(shí)現
Mysql-Server同時(shí)支持3種連接管理方式,包括No-Threads,One-Thread-Per-Connection和Pool-Threads。No-Threads表示處理連接使用主線(xiàn)程處理,不額外創(chuàng )建線(xiàn)程,這種方式主要用于調試;One-Thread-Per-Connection是線(xiàn)程池出現以前最常用的方式,為每一個(gè)連接創(chuàng )建一個(gè)線(xiàn)程服務(wù);Pool-Threads則是本文所討論的線(xiàn)程池方式。Mysql-Server通過(guò)一組函數指針來(lái)同時(shí)支持3種連接管理方式,對于特定的方式,將函數指針設置成特定的回調函數,連接管理方式通過(guò)thread_handling參數控制,代碼如下:
if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION) one_thread_per_connection_scheduler(thread_scheduler, &max_connections, &connection_count);else if (thread_handling == SCHEDULER_NO_THREADS) one_thread_scheduler(thread_scheduler);else pool_of_threads_scheduler(thread_scheduler, &max_connections,&connection_count);
連接管理流程
通過(guò)poll監聽(tīng)mysql端口的連接請求
收到連接后,調用accept接口,創(chuàng )建通信socket
初始化thd實(shí)例,vio對象等
根據thread_handling方式設置,初始化thd實(shí)例的scheduler函數指針
調用scheduler特定的add_connection函數新建連接
下面代碼展示了scheduler_functions模板和線(xiàn)程池對模板回調函數的實(shí)現,這個(gè)是多種連接管理的核心。
struct scheduler_functions { uint max_threads; uint *connection_count; ulong *max_connections; bool (*init)(void); bool (*init_new_connection_thread)(void); void (*add_connection)(THD *thd); void (*thd_wait_begin)(THD *thd, int wait_type); void (*thd_wait_end)(THD *thd); void (*post_kill_notification)(THD *thd); bool (*end_thread)(THD *thd, bool cache_thread); void (*end)(void);};static scheduler_functions tp_scheduler_functions= { 0, // max_threadsNULL,NULL, tp_init, // initNULL, // init_new_connection_threadtp_add_connection, // add_connectiontp_wait_begin, // thd_wait_begin tp_wait_end, // thd_wait_endtp_post_kill_notification, // post_kill_notification NULL, // end_threadtp_end // end };
線(xiàn)程池的相關(guān)參數
thread_handling:表示線(xiàn)程池模型。 thread_pool_size:表示線(xiàn)程池的group個(gè)數,一般設置為當前CPU核心數目。理想情況下,一個(gè)group一個(gè)活躍的工作線(xiàn)程,達到充分利用CPU的目的。 thread_pool_stall_limit:用于timer線(xiàn)程定期檢查group是否“停滯”,參數表示檢測的間隔。 thread_pool_idle_timeout:當一個(gè)worker空閑一段時(shí)間后會(huì )自動(dòng)退出,保證線(xiàn)程池中的工作線(xiàn)程在滿(mǎn)足請求的情況下,保持比較低的水平。 thread_pool_oversubscribe:該參數用于控制CPU核心上“超頻”的線(xiàn)程數。這個(gè)參數設置值不含listen線(xiàn)程計數。 threadpool_high_prio_mode:表示優(yōu)先隊列的模式。
線(xiàn)程池實(shí)現
上面描述了Mysql-Server如何管理連接,這節重點(diǎn)描述線(xiàn)程池的實(shí)現框架,以及關(guān)鍵接口。如圖1
每一個(gè)綠色的方框代表一個(gè)group,group數目由thread_pool_size參數決定。每個(gè)group包含一個(gè)優(yōu)先隊列和普通隊列,包含一個(gè)listener線(xiàn)程和若干個(gè)工作線(xiàn)程,listener線(xiàn)程和worker線(xiàn)程可以動(dòng)態(tài)轉換,worker線(xiàn)程數目由工作負載決定,同時(shí)受到thread_pool_oversubscribe設置影響。此外,整個(gè)線(xiàn)程池有一個(gè)timer線(xiàn)程監控group,防止group“停滯”。
關(guān)鍵接口
1. tp_add_connection[處理新連接]
1) 創(chuàng )建一個(gè)connection對象
2) 根據thread_id%group_count確定connection分配到哪個(gè)group
3) 將connection放進(jìn)對應group的隊列
4) 如果當前活躍線(xiàn)程數為0,則創(chuàng )建一個(gè)工作線(xiàn)程
2. worker_main[工作線(xiàn)程]
1) 調用get_event獲取請求
2) 如果存在請求,則調用handle_event進(jìn)行處理
3) 否則,表示隊列中已經(jīng)沒(méi)有請求,退出結束。
3. get_event[獲取請求]
1) 獲取一個(gè)連接請求
2) 如果存在,則立即返回,結束
3) 若此時(shí)group內沒(méi)有listener,則線(xiàn)程轉換為listener線(xiàn)程,阻塞等待
4) 若存在listener,則將線(xiàn)程加入等待隊列頭部
5) 線(xiàn)程休眠指定的時(shí)間(thread_pool_idle_timeout)
6) 如果依然沒(méi)有被喚醒,是超時(shí),則線(xiàn)程結束,結束退出
7) 否則,表示隊列里有連接請求到來(lái),跳轉1
備注:獲取連接請求前,會(huì )判斷當前的活躍線(xiàn)程數是否超過(guò)了
thread_pool_oversubscribe+1,若超過(guò)了,則將線(xiàn)程進(jìn)入休眠狀態(tài)。
4. handle_event[處理請求]
1) 判斷連接是否進(jìn)行登錄驗證,若沒(méi)有,則進(jìn)行登錄驗證
2) 關(guān)聯(lián)thd實(shí)例信息
3) 獲取網(wǎng)絡(luò )數據包,分析請求
4) 調用do_command函數循環(huán)處理請求
5) 獲取thd實(shí)例的套接字句柄,判斷句柄是否在epoll的監聽(tīng)列表中
6) 若沒(méi)有,調用epoll_ctl進(jìn)行關(guān)聯(lián)
7) 結束
5.listener[監聽(tīng)線(xiàn)程]
1) 調用epoll_wait進(jìn)行對group關(guān)聯(lián)的套接字監聽(tīng),阻塞等待
2) 若請求到來(lái),從阻塞中恢復
3) 根據連接的優(yōu)先級別,確定是放入普通隊列還是優(yōu)先隊列
4) 判斷隊列中任務(wù)是否為空
5) 若隊列為空,則listener轉換為worker線(xiàn)程
6) 若group內沒(méi)有活躍線(xiàn)程,則喚醒一個(gè)線(xiàn)程
備注:這里epoll_wait監聽(tīng)group內所有連接的套接字,然后將監聽(tīng)到的連接
請求push到隊列,worker線(xiàn)程從隊列中獲取任務(wù),然后執行。
6. timer_thread[監控線(xiàn)程]
1) 若沒(méi)有listener線(xiàn)程,并且最近沒(méi)有io_event事件
2) 則創(chuàng )建一個(gè)喚醒或創(chuàng )建一個(gè)工作線(xiàn)程
3) 若group最近一段時(shí)間沒(méi)有處理請求,并且隊列里面有請求,則
4) 表示group已經(jīng)stall,則喚醒或創(chuàng )建線(xiàn)程
5)檢查是否有連接超時(shí)
備注:timer線(xiàn)程通過(guò)調用check_stall判斷group是否處于stall狀態(tài),通過(guò)調用timeout_check檢查客戶(hù)端連接是否超時(shí)。
7.tp_wait_begin[進(jìn)入等待狀態(tài)流程]
1) active_thread_count減1,waiting_thread_count加1
2)設置connection->waiting= true
3) 若活躍線(xiàn)程數為0,并且任務(wù)隊列不為空,或者沒(méi)有監聽(tīng)線(xiàn)程,則
4) 喚醒或創(chuàng )建一個(gè)線(xiàn)程
8.tp_wait_end[結束等待狀態(tài)流程]
1) 設置connection的waiting狀態(tài)為false
2) active_thread_count加1,waiting_thread_count減1
備注:
1)waiting_threads這個(gè)list里面的線(xiàn)程是空閑線(xiàn)程,并非等待線(xiàn)程,所謂空閑線(xiàn)程是隨時(shí)可以處理任務(wù)的線(xiàn)程,而等待線(xiàn)程則是因為等待鎖,或等待io操作等無(wú)法處理任務(wù)的線(xiàn)程。
2)tp_wait_begin和tp_wait_end的主要作用是由于匯報狀態(tài),即使更新active_thread_count和waiting_thread_count的信息。
9. tp_init/tp_end
分別調用thread_group_init和thread_group_close來(lái)初始化和銷(xiāo)毀線(xiàn)程池
線(xiàn)程池與連接池
連接池通常實(shí)現在Client端,是指應用(客戶(hù)端)創(chuàng )建預先創(chuàng )建一定的連接,利用這些連接服務(wù)于客戶(hù)端所有的DB請求。如果某一個(gè)時(shí)刻,空閑的連接數小于DB的請求數,則需要將請求排隊,等待空閑連接處理。通過(guò)連接池可以復用連接,避免連接的頻繁創(chuàng )建和釋放,從而減少請求的平均響應時(shí)間,并且在請求繁忙時(shí),通過(guò)請求排隊,可以緩沖應用對DB的沖擊。線(xiàn)程池實(shí)現在server端,通過(guò)創(chuàng )建一定數量的線(xiàn)程服務(wù)DB請求,相對于one-conection-per-thread的一個(gè)線(xiàn)程服務(wù)一個(gè)連接的方式,線(xiàn)程池服務(wù)的最小單位是語(yǔ)句,即一個(gè)線(xiàn)程可以對應多個(gè)活躍的連接。通過(guò)線(xiàn)程池,可以將server端的服務(wù)線(xiàn)程數控制在一定的范圍,減少了系統資源的競爭和線(xiàn)程上下文切換帶來(lái)的消耗,同時(shí)也避免出現高連接數導致的高并發(fā)問(wèn)題。連接池和線(xiàn)程池相輔相成,通過(guò)連接池可以減少連接的創(chuàng )建和釋放,提高請求的平均響應時(shí)間,并能很好地控制一個(gè)應用的DB連接數,但無(wú)法控制整個(gè)應用集群的連接數規模,從而導致高連接數,通過(guò)線(xiàn)程池則可以很好地應對高連接數,保證server端能提供穩定的服務(wù)。如圖2所示,每個(gè)web-server端維護了3個(gè)連接的連接池,對于連接池的每個(gè)連接實(shí)際不是獨占db-server的一個(gè)worker,而是可能與其他連接共享。這里假設db-server只有3個(gè)group,每個(gè)group只有一個(gè)worker,每個(gè)worker處理了2個(gè)連接的請求。
線(xiàn)程池優(yōu)化
1.調度死鎖解決
引入線(xiàn)程池解決了多線(xiàn)程高并發(fā)的問(wèn)題,但也帶來(lái)一個(gè)隱患。假設,A,B兩個(gè)事務(wù)被分配到不同的group中執行,A事務(wù)已經(jīng)開(kāi)始,并且持有鎖,但由于A(yíng)所在的group比較繁忙,導致A執行一條語(yǔ)句后,不能立即獲得調度執行;而B(niǎo)事務(wù)依賴(lài)A事務(wù)釋放鎖資源,雖然B事務(wù)可以被調度起來(lái),但由于無(wú)法獲得鎖資源,導致仍然需要等待,這就是所謂的調度死鎖。由于一個(gè)group會(huì )同時(shí)處理多個(gè)連接,但多個(gè)連接不是對等的。比如,有的連接是第一次發(fā)送請求;而有的連接對應的事務(wù)已經(jīng)開(kāi)啟,并且持有了部分鎖資源。為了減少鎖資源爭用,后者顯然應該比前者優(yōu)先處理,以達到盡早釋放鎖資源的`目的。因此在group里面,可以添加一個(gè)優(yōu)先級隊列,將已經(jīng)持有鎖的連接,或者已經(jīng)開(kāi)啟的事務(wù)的連接發(fā)起的請求放入優(yōu)先隊列,工作線(xiàn)程首先從優(yōu)先隊列獲取任務(wù)執行。
2.大查詢(xún)處理
假設一種場(chǎng)景,某個(gè)group里面的連接都是大查詢(xún),那么group里面的工作線(xiàn)程數很快就會(huì )達到thread_pool_oversubscribe參數設置值,對于后續的連接請求,則會(huì )響應不及時(shí)(沒(méi)有更多的連接來(lái)處理),這時(shí)候group就發(fā)生了stall。通過(guò)前面分析知道,timer線(xiàn)程會(huì )定期檢查這種情況,并創(chuàng )建一個(gè)新的worker線(xiàn)程來(lái)處理請求。如果長(cháng)查詢(xún)來(lái)源于業(yè)務(wù)請求,則此時(shí)所有g(shù)roup都面臨這種問(wèn)題,此時(shí)主機可能會(huì )由于負載過(guò)大,導致hang住的情況。這種情況線(xiàn)程池本身無(wú)能為力,因為源頭可能是爛SQL并發(fā),或者SQL沒(méi)有走對執行計劃導致,通過(guò)其他方法,比如SQL高低水位限流或者SQL過(guò)濾手段可以應急處理。但是,還有另外一種情況,就是dump任務(wù)。很多下游依賴(lài)于數據庫的原始數據,通常通過(guò)dump命令將數據拉到下游,而這種dump任務(wù)通常都是耗時(shí)比較長(cháng),所以也可以認為是大查詢(xún)。如果dump任務(wù)集中在一個(gè)group內,并導致其他正常業(yè)務(wù)請求無(wú)法立即響應,這個(gè)是不能容忍的,因為此時(shí)數據庫并沒(méi)有壓力,只是因為采用了線(xiàn)程池策略,才導致了請求響應不及時(shí),為了解決這個(gè)問(wèn)題,我們將group中處理dump任務(wù)的線(xiàn)程不計入thread_pool_oversubscribe累計值,避免上述問(wèn)題。
one-connection-per-thread
根據scheduler_functions的模板,我們也可以列出one-connection-per-thread方式的幾個(gè)關(guān)鍵函數。
static scheduler_functions con_per_functions= { max_connection+1, // max_threads NULL, NULL, NULL, // init Init_new_connection_handler_thread, // init_new_connection_thread create_thread_to_handle_connection, // add_connection NULL, // thd_wait_begin NULL, // thd_wait_end NULL, // post_kill_notification one_thread_per_connection_end, // end_thread NULL // end };
1.init_new_connection_handler_thread
這個(gè)接口比較簡(jiǎn)單,主要是調用pthread_detach,將線(xiàn)程設置為detach狀態(tài),線(xiàn)程結束后自動(dòng)釋放所有資源。
2.create_thread_to_handle_connection
這個(gè)接口是處理新連接的接口,對于線(xiàn)程池而言,會(huì )從thread_id%group_size對應的group中獲取一個(gè)線(xiàn)程來(lái)處理,而one-connection-per-thread方式則會(huì )判斷是否有thread_cache可以使用,如果沒(méi)有則新建線(xiàn)程來(lái)處理。具體邏輯如下:
(1).判斷緩存的線(xiàn)程數是否使用完(比較blocked_pthread_count 和wake_pthread大小)
(2).若還有緩存線(xiàn)程,將thd加入waiting_thd_list的隊列,喚醒一個(gè)等待COND_thread_cache的線(xiàn)程
(3).若沒(méi)有,創(chuàng )建一個(gè)新的線(xiàn)程處理,線(xiàn)程的入口函數是do_handle_one_connection
(4).調用add_global_thread加入thd數組。
3.do_handle_one_connection
這個(gè)接口被create_thread_to_handle_connection調用,處理請求的主要實(shí)現接口。
(1).循環(huán)調用do_command,從socket中讀取網(wǎng)絡(luò )包,并且解析執行;
(2). 當遠程客戶(hù)端發(fā)送關(guān)閉連接COMMAND(比如COM_QUIT,COM_SHUTDOWN)時(shí),退出循環(huán)
(3).調用close_connection關(guān)閉連接(thd->disconnect());
(4).調用one_thread_per_connection_end函數,確認是否可以復用線(xiàn)程
(5).根據返回結果,確定退出工作線(xiàn)程還是繼續循環(huán)執行命令。
4.one_thread_per_connection_end
判斷是否可以復用線(xiàn)程(thread_cache)的主要函數,邏輯如下:
(1).調用remove_global_thread,移除線(xiàn)程對應的thd實(shí)例
(2).調用block_until_new_connection判斷是否可以重用thread
(3).判斷緩存的線(xiàn)程是否超過(guò)閥值,若沒(méi)有,則blocked_pthread_count++;
(4).阻塞等待條件變量COND_thread_cache
(5).被喚醒后,表示有新的thd需要重用線(xiàn)程,將thd從waiting_thd_list中移除,使用thd初始化線(xiàn)程的thd->thread_stack
(6).調用add_global_thread加入thd數組。
(7).如果可以重用,返回false,否則返回ture
線(xiàn)程池與epoll
在引入線(xiàn)程池之前,server層只有一個(gè)監聽(tīng)線(xiàn)程,負責監聽(tīng)mysql端口和本地unixsocket的請求,對于每個(gè)新的連接,都會(huì )分配一個(gè)獨立線(xiàn)程來(lái)處理,因此監聽(tīng)線(xiàn)程的任務(wù)比較輕松,mysql通過(guò)poll或select方式來(lái)實(shí)現IO的多路復用。引入線(xiàn)程池后,除了server層的監聽(tīng)線(xiàn)程,每個(gè)group都有一個(gè)監聽(tīng)線(xiàn)程負責監聽(tīng)group內的所有連接socket的連接請求,工作線(xiàn)程不負責監聽(tīng),只處理請求。對于overscribe為1000的線(xiàn)程池設置,每個(gè)監聽(tīng)線(xiàn)程需要監聽(tīng)1000個(gè)socket的請求,監聽(tīng)線(xiàn)程采用epoll方式來(lái)實(shí)現監聽(tīng)。
Select,poll,epoll都是IO多路復用機制,IO多路復用通過(guò)一種機制,可以監聽(tīng)多個(gè)fd(描述符),比如socket,一旦某個(gè)fd就緒(讀就緒或寫(xiě)就緒),能夠通知程序進(jìn)行相應的讀寫(xiě)操作。epoll相對于select和poll有了很大的改進(jìn),首先epoll通過(guò)epoll_ctl函數注冊,注冊時(shí),將所有fd拷貝進(jìn)內核,只拷貝一次不需要重復拷貝,而每次調用poll或select時(shí),都需要將fd集合從用戶(hù)空間拷貝到內核空間(epoll通過(guò)epoll_wait進(jìn)行等待);其次,epoll為每個(gè)描述符指定了一個(gè)回調函數,當設備就緒時(shí),喚醒等待者,通過(guò)回調函數將描述符加入到就緒鏈表,無(wú)需像select,poll方式采用輪詢(xún)方式;最后select默認只支持1024個(gè)fd,epoll則沒(méi)有限制,具體數字可以參考cat /proc/sys/fs/file-max的設置。epoll貫穿在線(xiàn)程池使用的過(guò)程中,下面我就epoll的創(chuàng )建,使用和銷(xiāo)毀生命周期來(lái)描述epoll在線(xiàn)程中是如何使用的。
線(xiàn)程池初始化,epoll通過(guò)epoll_create函數創(chuàng )建epoll文件描述符,實(shí)現函數是thread_group_init;
端口監聽(tīng)線(xiàn)程監聽(tīng)到請求后,創(chuàng )建socket,并創(chuàng )建THD和connection對象,放在對應的group隊列中;
工作線(xiàn)程獲取該connection對象時(shí),若還未登錄,則進(jìn)行登錄驗證
若socket還未注冊到epoll,則調用epoll_ctl進(jìn)行注冊,注冊方式是EPOLL_CTL_ADD,并將connection對象放入epoll_event結構體中
若是老連接的請求,仍然需要調用epoll_ctl注冊,注冊方式是EPOLL_CTL_MOD
group內的監聽(tīng)線(xiàn)程調用epoll_wait來(lái)監聽(tīng)注冊的fd,epoll是一種同步IO方式,所以會(huì )進(jìn)行等待
請求到來(lái)時(shí),獲取epoll_event結構體中的connection,放入到group中的隊列
線(xiàn)程池銷(xiāo)毀時(shí),調用thread_group_close將epoll關(guān)閉。
備注:
1.注冊在epoll的fd,若請求就緒,則將對應的event放入到events數組,并將該fd的事務(wù)類(lèi)型清空,因此對于老的連接請求,依然需要調用epoll_ctl(pollfd, EPOLL_CTL_MOD, fd, &ev)來(lái)注冊。
線(xiàn)程池函數調用關(guān)系
(1)創(chuàng )建epoll
tp_init->thread_group_init->tp_set_threadpool_size->io_poll_create->epoll_create
(2)關(guān)閉epoll
tp_end->thread_group_close->thread_group_destroy->close(pollfd)
(3)關(guān)聯(lián)socket描述符
handle_event->start_io->io_poll_associate_fd->io_poll_start_read->epoll_ctl
(4)處理連接請求
handle_event->threadpool_process_request->do_command->dispatch_command->mysql_parse->mysql_execute_command
(5)工作線(xiàn)程空閑時(shí)
worker_main->get_event->pthread_cond_timedwait
等待thread_pool_idle_timeout后,退出。
(6)監聽(tīng)epoll
worker_main->get_event->listener->io_poll_wait->epoll_wait
(7)端口監聽(tīng)線(xiàn)程
main->mysqld_main->handle_connections_sockets->poll
one-connection-per-thread函數調用關(guān)系
(1) 工作線(xiàn)程等待請求
handle_one_connection->do_handle_one_connection->do_command->my_net_read->net_read_packet->net_read_packet_header->net_read_raw_loop->vio_read->vio_socket_io_wait->vio_io_wait->poll
備注:與線(xiàn)程池的工作線(xiàn)程有監聽(tīng)線(xiàn)程幫助其監聽(tīng)請求不同,one-connection-per-thread方式的工作線(xiàn)程在空閑時(shí),會(huì )調用poll阻塞等待網(wǎng)絡(luò )包過(guò)來(lái);
而線(xiàn)程池的工作線(xiàn)程只需要專(zhuān)心處理請求即可,所以使用也更充分。
【最新線(xiàn)程池介紹論文】相關(guān)文章:
神仙池景區介紹05-02
甲魚(yú)青魚(yú)同池養殖技術(shù)論文05-25
調蓄池工程的設計研究論文04-12
《太液池歌》詩(shī)詞介紹11-14
最新碩士論文開(kāi)題報告框架介紹06-27
Java線(xiàn)程面試題02-23
多線(xiàn)程人生的雜文隨筆07-04
曾鞏《北池小會(huì )》詩(shī)文相關(guān)介紹11-22
半池童真半池哀傷散文欣賞03-06