本文主要是介绍1.10 双线程高效下载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
(一)题目
网络上下载数据,然后存储到硬盘上。简单做法是:先下载一块然后写到硬盘,然后再下载,再写到硬盘上。
缺点:需要先下载完才能写入硬盘,下载和写是串行操作。
改进:让两个线程并行进行,设置缓冲区,采用信号量的形式。
下载线程,只要缓冲区有空余就下载,下载完成之后告诉写线程缓冲区有数据了。
写线程,只要缓冲区有数据就写入,写完后告诉下载线程缓冲区有空闲了。
代码如下:
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; //当任务全部下载完成,并且所有的数据都存储到硬盘中,进程才可以结束}
}
这篇关于1.10 双线程高效下载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!