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

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

一,题目

        网络上下载数据,然后存储到硬盘上。简单做法是:先下载一块然后写到硬盘,然后再下载,再写到硬盘上。

        缺点:需要先下载完才能写入硬盘,下载和写是串行操作。

        改进:让两个线程并行进行,设置缓冲区,采用信号量的形式。

                    下载线程,只要缓冲区有空余就下载,下载完成之后告诉写线程缓冲区有数据了。

                     写线程,只要缓冲区有数据就写入,写完后告诉下载线程缓冲区有空闲了。

二,核心源码
//downloads a block from Internet sequentially in each call  
//return true, if the entire file is downloaded, otherwise false.  
bool GetBlockFromNet(Block* out_block);  
  
//writes a block to hard disk  
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();  
};  
//----------------------------------------------------  
  
//1.确定使用信号量,而非互斥量,保证并行操作  
//2.当缓冲区并不满并且下载没结束时,下载线程运行  
//3.当缓冲区并不空并且下载没结束时,存储线程运行  
  
#define MAX_COUNT 1000  
Block g_Buffer[MAX_COUNT]; //缓冲区数组,模拟循环队列  
Thread g_Download(ProcA);  
Thread g_Write(ProcB);  
  
//一开始缓冲区空间为MAX_COUNT,整个缓冲区可供下载的数据填充  
Semaphore ForDownload(MAX_COUNT,MAX_COUNT);  
//一开始缓冲区无数据可供存储  
Semaphore ForWrite(0,MAX_COUNT);  
  
//下载任务是否完成  
bool isDone;  
//下载的数据从缓冲区的哪个地方开始填充  
int in_index;  
//存储的数据从缓冲区的哪个地方开始提取  
int out_index;  
  
void ProcA()//下载线程   
{  
    while(true)  
    {  
        //首先取得一个空闲空间,以便下载数据填充  
        ForDownload.Unsignal();  
        //填充  
        isDone=GetBlockFromNet(g_Buffer+in_index);  
        //更新索引  
        in_index=(in_index+1)%MAX_COUNT;  
        //提示存储线程可以工作  
        ForWrite.Signal();  
      
        //当任务全部下载完成,进程就可以结束了  
        if(isDone)  
              break;  
    }  
}  
  
void ProcB()//写入线程   
{  
    while(true)  
    {  
        //查询时候有数据可供存储  
        ForWrite.Unsignal();  
        //存储  
        WriteBlockToDisk(g_Buffer+out_index);  
        //更新索引  
        out_index=(out_index+1)%MAX_COUNT;  
        //将空闲空间还给缓冲区  
        ForDownload.Signal();  
      
        //当任务全部下载完成,并且所有的数据都存储到硬盘中,进程才可以结束  
        if(isDone&&in_index==out_index)  
            break;  
    }  
}  
  
int main()  
{  
    isDone=false;  
    in_index=0;  
    out_index=0;  
    g_Download.Start();  
    g_Write.Start();  
}  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值