编程之美 1.10 双线程高效下载

本文介绍了一种利用双线程实现数据高效下载的方法,通过信号量和互斥量协调下载线程与写入线程的工作,确保数据的正确下载与存储。在固定的缓冲区大小下,下载线程与写入线程能够无缝配合,提高下载效率。
1.10 双线程高效下载

        我们经常需要编写程序,从网络上下载数据,然后存储到硬盘上。一个简单的做法就是下载一块数据,写入硬盘,然后再下载,再写入硬盘……不断重复这个过程,直到所有的内容下载完毕并写入硬盘为止。
现在给出以下几个前提:
1、假设所有数据块的大小都是固定的,可以使用一个全局缓冲区:
Block g_buffer[BUFFER_COUNT]
2、可以使用的API

// 下载数据到缓存
bool GetBlockFromNet(Block * out_block);
// 写数据到硬盘
bool WriteBlockToDisk(Block *in_block);

// 线程类
class Thread
{
public:
	Thread(void(*work_func)());
	~Thread();
	void Start();
	void Abort();
};
// 信号量
class Semaphore
{
public:
	Semaphore(int count, int max_count);
	~Semaphore();
	void Unsignal();
	void Signal();
};

// 互斥量
class Mutex
{
public:
	WaitMutex();
	ReleaseMutex();
};

现在要求使用上面提供的API编写程序完成数据的下载和写入。

解题思路:
  1. 终止条件:数据全部下载完,并写入硬盘即终止。
  2. 线程同步量的选择:为了保证下载线程和写入线程同时工作,使用信号量semaohore。
  3. 下载和写入程序协同工作:即缓存区满停止下载,缓冲区为空停止写入。
  4. 缓冲区的数据接口,由于使用的是全局数组进行存储,可以把它当做循环队列使用。

示例代码:

// 缓冲区大小
#define BUFFER_SIZE = 100
// 缓冲区
Block g_buffer[BUFFER_SIZE];

// 下载数据线程
Thread g_getThread(getData);
// 写数据线程
Thread g_writeThread(writeData);

// 缓冲区满信号量
semaphore g_bufferFull(0, BUFFER_SIZE);
// 缓冲区空信号量
semaphore g_bufferEmpty(BUFFER_SIZE, BUFFER_SIZE);

// 下载完成标志
bool g_downloadComplete;

// 数据入索引
int in_index = 0;

// 数据出索引
int out_index = 0;



void main()
{
	g_downloadComplete = false;
	g_getThread.start();
	g_writeThread.start();
}

// 下载数据线程
void getData()
{
	while (1)
	{
		// 增加数据到缓冲区,空信号量减1
		g_bufferEmpty.Unsignal();
		g_downloadComplete = getBlockFromNet(g_buffer + in_index);
		in_index = (in_index + 1) % BUFFER_SIZE;

		// 增加数据到缓冲区,满信号量加1
		g_bufferFull.Signal();
		if (g_downloadComplete)
			break;
	}
}

// 写数据线程
void getData()
{
	while (1)
	{
		// 缓冲区取出数据,满信号量减1
		g_bufferFull.Unsignal();
		g_downloadComplete = WriteBlockToDisk(g_buffer + out_index);
		out_index = (out_index + 1) % BUFFER_SIZE;

		// 缓冲区取出数据,空信号量加1
		g_bufferEmpty.Signal();
		if (g_downloadComplete && (in_index == out_index))
			break;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值