您的位置:首页 > 编程语言

【编程之美】双线程高效下载

2014-03-07 18:09 363 查看
假设提供了以下方法:

bool GetBlockFromNet(Block *out_block);

bool WriteBlockToDisk(Block *in_block);

想实现高效当然是创建两个线程,A负责获取网络数据,B负责写入数据到硬盘,难点在于如何合理分配两个线程之间的工作!

分析与解法:

1.什么时候才算完成任务?

下载完毕并且完全存储到硬盘上,两个线程才能正常终止。

2.希望两个线程能同时工作,又不发生冲突,用什么方法?

使用Mutex(互斥量),下载时不能存储所以弃用。

使用Semaphore(信号量)是更好的选择。

3.下载与存储的必要条件

buffer满的时候和所有内容下载完毕,应该停止下载。

buffer为空时,没必要运行存储线程。

核心程序
#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);
bool g_downloadComplete = false;
int in_index = 0;//表示当前下载线程正在处理的数据块的编号
int out_index = 0;//表示当前存储线程正在处理的数据块的编号

void main()
{
g_ThreadA.start();//启动下载线程
g_ThreadB.start();//启动存储线程
Wait();
}

//下载线程的工作函数
void ProcA()
{
while(true)
{
//申请一个空的数据块的资源
g_seEmpty.Unsignal();
//申请到空的数据块,向in_index指向的BLOCK下载数据
g_downloadComplete = GetBlockFromNet(g_buffer + in_index);
//in_index更新
in_index = (in_index + 1) % BUFFER_CONUT;
g_seFull.Signal();//报告又有一个新的数据块已经下载完毕,可以指向写入操作...
if(g_downloadComplete)
break;
}
}

//存储线程的工作函数
void ProcB()
{
while(true)
{
//申请一个满的数据块的资源
g_seFull.Unsignal();
//申请到满的数据块,从out_index指向的BLOCK获取数据,写入Disk。
WriteBlockToDisk(g_buffer + out_index);
//out_index更新
out_index = (out_index + 1) % BUFFER_CONUT;
g_seEmpty.Signal();//报告又有一个新的数据块已经写入完毕,可以下载覆盖其数据...
if(g_downloadComplete && out_index == in_index)
break;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: