(一)题目
网络上下载数据,然后存储到硬盘上。简单做法是:先下载一块然后写到硬盘,然后再下载,再写到硬盘上。
缺点:需要先下载完才能写入硬盘,下载和写是串行操作。
改进:让两个线程并行进行,设置缓冲区,采用信号量的形式。
下载线程,只要缓冲区有空余就下载,下载完成之后告诉写线程缓冲区有数据了。
写线程,只要缓冲区有数据就写入,写完后告诉下载线程缓冲区有空闲了。
代码如下:
class Thread {
public:
Thread(void (*work_func)());
~Thread();
void Start();
void Abort();
};
class Semaphore {
public:
Semaphore(int count, int max_count);
~Semaphore();
void Unsignal(); //count--
void Signal(); //count++
};
class Mutex {
public:
WaitMutex();
ReleaseMutex();
};
//如果使用Mutex,下载和存储线程将不能同时工作,因此,Semaphore是更好的选择
#define BUFFER_COUNT 100
Block g_buffer[BUFFER_COUNT];
Thread g_threadA(ProcA);
Thread g_threadB(ProcB);
Semaphore g_seFull(0, BUFFER_COUNT); //一开始缓冲区无数据可供存储
Semaphore g_seEmpty(BUFFER_COUNT, BUFFER_COUNT); //一开始缓冲区空间为BUFFER_COUNT,整个缓冲区可供下载的数据填充
bool g_downloadComplete; //下载任务是否完成
int in_index = 0; //下载的数据从缓冲区的哪个地方开始填充
int out_index = 0; //存储的数据从缓冲区的哪个地方开始提取
void main() {
g_downloadComplete = false;
g_threadA.Start();
g_threadB.Start();
}
void ProcA() {
while(true) {
g_seEmpty.Unsignal(); //首先取得一个空闲空间,以便下载数据填充
g_downloadComplete = GetBlockFromNet(g_buffer + in_index); //填充
in_index = (in_index + 1) % BUFFER_COUNT; //更新索引
g_seFull.Signal(); //提示存储线程可以工作
if(g_downloadComplete) break; //当任务全部下载完成,进程就可以结束了
}
}
void ProcB() {
while(true) {
g_seFull.Unsignal(); //查询时候有数据可供存储
WriteBlockToDisk(g_buffer + out_index); //存储
out_index = (out_index + 1) % BUFFER_COUNT; //更新索引
g_seEmpty.Signal(); //将空闲空间还给缓冲区
if(g_downloadComplete && out_index == in_index) break; //当任务全部下载完成,并且所有的数据都存储到硬盘中,进程才可以结束
}
}原文:http://blog.csdn.net/u010470972/article/details/39899453