建立異步操作組件:隊列和線程
6.25.2008
Kevin Lynx
引言
在一個高效的系統中,我們經常會將一些費時的操作轉換為異步操作。例如往數據庫中寫日志。如果數據庫
配置在網絡上,那么往數據庫中插入一些日志信息將非常慢(相對于程序其他部分)。
如何轉換為異步?
將類似于以上過程轉換為異步操作,一個典型的做法是:建立一個單獨的數據庫日志線程,一個線程安全的
隊列。要寫日志時,只需要往隊列里放入數據,數據庫日志線程則從這個隊列里取數據然后完成寫操作。
大致的過程類似于:




























將他們包裝起來
我們很有可能會在同一個系統中多次遇到類似需要轉換為異步操作的地方,如果每一次都手動去創建一個隊列和一
個線程,那將會多么乏味啊!懶惰的程序員喜歡重用各種代碼。所以,我自己覺得很有必要將這一切封裝起來。我
們只需要封裝這個隊列和創建線程的繁瑣細節,讓應用層全部專注于具體的邏輯處理:



















































我利用了已有的組件:線程安全的容器multi_list、包裝任意執行體的functor、線程維護類thread。那么,現在,
應用層只需要定義隊列節點類型,寫應用相關的回調函數(任意可被functor包裝的廣義函數)。(見附件例子)
之所以為這個組件加上init和release,是因為有些東西(例如COM)需要在線程啟動時初始化,而在線程快結束時釋放,例如對于
使用COM的應用來說,就需要在線程初始化時CoInitialize,結束時CoUninitialize。
閑說下其他東西
在本文的附件代碼里,你可以獲取到functor、thread、multi_list這些東西,所以我有必要提一下。
關于functor,你可以參看<實現functor - 增強型的函數指針>,基本上可以看成增強版的C回調函數;至于multi_list,基本上
是一個container adapter (套用下STL的概念),使用條件變量參與線程同步,據說效率要比簡單的互斥高點;至于thread,我需要
特別說下:
thread最為重要的就是為其附加了一個windows的消息隊列(只要調用PeekMessage之類的函數該隊列就存在),本意是可以讓其他線
程傳送數據到該線程,但是目前只用于線程退出,即其他線程可以在任何時候要求該線程安全地退出(該線程沒有阻塞的情況下,
阻塞時獲取不到消息)。我不知道這個安全退出策略是否真的有必要存在,但是我討厭看到各種撇腳的退出方法(例如設置全局標志
變量,增加額外的--沒封裝前---event對象之類)。
結束
不知道其他人是如何做這種異步轉換操作的,在這里我只是起個拋磚引玉的作用,歡迎大家提出意見。
例子下載
posted on 2008-06-25 15:47 Kevin Lynx 閱讀(5071) 評論(29) 編輯 收藏 引用 所屬分類: 通用編程