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

来源:互联网 发布:淘宝联盟返现到哪里 编辑:程序博客网 时间:2024/04/28 00:37

一,题目

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

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

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

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

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

        

二,核心源码


[html] view plaincopy
  1. //downloads a block from Internet sequentially in each call  
  2. //return true, if the entire file is downloaded, otherwise false.  
  3. bool GetBlockFromNet(Block* out_block);  
  4.   
  5. //writes a block to hard disk  
  6. bool WriteBlockToDisk(Block* in_block);  
  7.   
  8. class Thread  
  9. {  
  10. public:  
  11.     Thread(void (*work_func)());  
  12.     ~Thread();  
  13.     void Start();  
  14.     void Abort();  
  15. };  
  16.   
  17. class Semaphore  
  18. {  
  19. public:  
  20.     Semaphore(int count,int max_count);  
  21.     ~Semaphore();  
  22.     void Unsignal();  
  23.     void Signal();  
  24. };  
  25.   
  26. class Mutex  
  27. {  
  28. public:  
  29.     WaitMutex();  
  30.     ReleaseMutex();  
  31. };  
  32. //----------------------------------------------------  
  33.   
  34.   
  35.   
  36. //1.确定使用信号量,而非互斥量,保证并行操作  
  37. //2.当缓冲区并不满并且下载没结束时,下载线程运行  
  38. //3.当缓冲区并不空并且下载没结束时,存储线程运行  
  39.   
  40.   
  41. #define MAX_COUNT 1000  
  42. Block g_Buffer[MAX_COUNT]; //缓冲区数组,模拟循环队列  
  43. Thread g_Download(ProcA);  
  44. Thread g_Write(ProcB);  
  45.   
  46. //一开始缓冲区空间为MAX_COUNT,整个缓冲区可供下载的数据填充  
  47. Semaphore ForDownload(MAX_COUNT,MAX_COUNT);  
  48. //一开始缓冲区无数据可供存储  
  49. Semaphore ForWrite(0,MAX_COUNT);  
  50.   
  51. //下载任务是否完成  
  52. bool isDone;  
  53. //下载的数据从缓冲区的哪个地方开始填充  
  54. int in_index;  
  55. //存储的数据从缓冲区的哪个地方开始提取  
  56. int out_index;  
  57.   
  58. void ProcA()//下载线程   
  59. {  
  60.     while(true)  
  61.     {  
  62.         //首先取得一个空闲空间,以便下载数据填充  
  63.         ForDownload.Unsignal();  
  64.         //填充  
  65.         isDone=GetBlockFromNet(g_Buffer+in_index);  
  66.         //更新索引  
  67.         in_index=(in_index+1)%MAX_COUNT;  
  68.         //提示存储线程可以工作  
  69.         ForWrite.Signal();  
  70.       
  71.         //当任务全部下载完成,进程就可以结束了  
  72.         if(isDone)  
  73.               break;  
  74.     }  
  75. }  
  76.   
  77. void ProcB()//写入线程   
  78. {  
  79.     while(true)  
  80.     {  
  81.         //查询时候有数据可供存储  
  82.         ForWrite.Unsignal();  
  83.         //存储  
  84.         WriteBlockToDisk(g_Buffer+out_index);  
  85.         //更新索引  
  86.         out_index=(out_index+1)%MAX_COUNT;  
  87.         //将空闲空间还给缓冲区  
  88.         ForDownload.Signal();  
  89.       
  90.         //当任务全部下载完成,并且所有的数据都存储到硬盘中,进程才可以结束  
  91.         if(isDone&&in_index==out_index)  
  92.             break;  
  93.     }  
  94. }  
  95.   
  96. int main()  
  97. {  
  98.     isDone=false;  
  99.     in_index=0;  
  100.     out_index=0;  
  101.     g_Download.Start();  
  102.     g_Write.Start();  
  103. }  
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 网易邮箱密码忘记了怎么办 网易邮箱密码忘了怎么办 网易邮箱忘记邮箱账号怎么办 崩坏3三无号被盗怎么办 qq邮箱给58占用怎么办 支付宝邮箱被占用怎么办 苹果手机下载不了qq怎么办 附件预览时发生错误怎么办 手机下载的压缩包打不开怎么办 邮箱提示中转站剩余容量不足怎么办 手机邮箱密码忘记了怎么办 垃圾邮件被系统删除了怎么办 邮箱里的邮件下载不了怎么办 qq邮箱下载不了文件怎么办 苹果手机忘记邮箱密码怎么办 oppo手机安装包损坏怎么办 手机安装包损坏无法安装怎么办 手机qq安装包损坏了怎么办 安装包损坏无法安装怎么办 方舟生存进化安装包损坏怎么办 如果安装包坏了怎么办 酷狗下载音乐收费怎么办 酷狗下载歌曲收费怎么办 酷狗音乐下载歌曲要钱怎么办 酷狗音乐下载要钱怎么办 手机酷狗音乐下载收费怎么办 咪咕视频静音了怎么办 卡西欧自拍神器死机了怎么办 手机一自拍就死机怎么办 微信怎么黑屏了怎么办 宝宝睡袋买大了怎么办 社保中间断了一年怎么办 京东阅读换手机怎么办 酷狗自动续费怎么办 qq音乐下载需要钱怎么办 电脑播放音乐没声音怎么办 酷狗账号注销了怎么办 电脑酷狗音乐没有声音怎么办 百度云的视频被净网怎么办 v380用户名或密码错误怎么办 课堂派没签到的怎么办