1.10 雙執行緒高效下載
偽碼給出了典型的生產者消費者問題解答,用一個訊號量(semaphore)表示剩餘空閒塊數(g_seEmpty),一個訊號量表示已下載記錄數(g_seFull)。
下載執行緒中消耗空閒塊,所以先g_seEmpty.Unsignal(),相當於P(g_seEmpty),完成後g_seFull.Signal(),相當於V(g_seFull)。寫磁碟執行緒則恰好相反,先g_seFull.Unsignal(),相當於P(g_seFull),完成後g_seEmpty.Signal(),相當於V(g_seEmpty)。
值得注意的是Thread的建構函式中指定的是函式指標:Thread(void (*work_func)());這樣就可以為不同的執行緒指定不同的工作函式了。
回顧一下PV操作:
procedure p(var s:samephore);
{
s.value=s.value-1;
if (s.value<0) asleep(s.queue);
}
procedure v(var s:samephore);
{
s.value=s.value+1;
if (s.value<=0) wakeup(s.queue);
}
與semaphore的機制是一樣的,當使用semaphore進行計數時,count==0時將當前的thread阻塞。
後續問題:
1.多個下載執行緒的實現
TODO
如果直接加入多個下載執行緒,由於下載完成順序是不一定的,如何保證訪問儲存的順序是有序的?為每一個block加鎖?
2.windows中有哪些API可以瞭解使用者是否在使用滑鼠或者鍵盤
(1)GetInputState
函式原型: BOOL GetInputState(VOID);
函式功能:該函式確定在當前執行緒的訊息佇列中是否有要處理的滑鼠,鍵盤訊息.
注意事項:返回值指定是否發生了滑鼠,鍵盤輸入.如果檢測到輸入的話,則返回值為非零值,否則返回值為零
(2)GetLastInputInfo
函式原型:BOOL WINAPI GetLastInputInfo( __out PLASTINPUTINFO plii);
函式功能:獲取上次輸入操作的時間
引數:[out] 型別:PLASTINPUTINFO結構一個指向接收到最後一個輸入事件時間的LASTINPUTINFO結構指標。
返回值:如果呼叫函式成功,返回值為非零。 如果呼叫函式失敗,返回值為零。
說明:呼叫函式GetLastInputInfo()以後, 結構成員lpi.dwTime 中的值並非上次輸入事件發生以後的毫秒數。而是上次輸入事件發生時的系統執行時間。相當於上次輸入事件發生時執行了lpi.dwTime=::GetTickCount()。::GetTickCount()-lpi.dwTime才是上次輸入事件發生以後的毫秒數。
函式原型: BOOL GetInputState(VOID);
函式功能:該函式確定在當前執行緒的訊息佇列中是否有要處理的滑鼠,鍵盤訊息.
注意事項:返回值指定是否發生了滑鼠,鍵盤輸入.如果檢測到輸入的話,則返回值為非零值,否則返回值為零
(2)GetLastInputInfo
函式原型:BOOL WINAPI GetLastInputInfo( __out PLASTINPUTINFO plii);
函式功能:獲取上次輸入操作的時間
引數:[out] 型別:PLASTINPUTINFO結構一個指向接收到最後一個輸入事件時間的LASTINPUTINFO結構指標。
返回值:如果呼叫函式成功,返回值為非零。 如果呼叫函式失敗,返回值為零。
說明:呼叫函式GetLastInputInfo()以後, 結構成員lpi.dwTime 中的值並非上次輸入事件發生以後的毫秒數。而是上次輸入事件發生時的系統執行時間。相當於上次輸入事件發生時執行了lpi.dwTime=::GetTickCount()。::GetTickCount()-lpi.dwTime才是上次輸入事件發生以後的毫秒數。
比較著名的問題有:生產者消費者問題,讀者寫者問題,迴圈佇列讀寫問題,等。