编程之美复习笔记
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才是上次输入事件发生以后的毫秒数。
比较著名的问题有:生产者消费者问题,读者写者问题,循环队列读写问题,等。
你问我生命中还有什么可追寻?