大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C++技巧 > C++双线程下载

C++双线程下载

关键词:C++双线程下载  阅读(761) 赞(11)

[摘要]本文是对C++双线程下载的讲解,对学习C++编程技术有所帮助,与大家分享。

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

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

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

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

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

【代码】

C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//
/*
version:1.0
date:2014/7/4
*/
//---------------------API------------------------------
//downloadsablockfromInternetsequentiallyineachcall
//returntrue,iftheentirefileisdownloaded,otherwisefalse.
boolGetBlockFromNet(Block*out_block);

//writesablocktoharddisk
boolWriteBlockToDisk(Block*in_block);

classThread
{
public:
Thread(void(*work_func)());
~Thread();
voidStart();
voidAbort();
};

classSemaphore
{
public:
Semaphore(intcount,intmax_count);
~Semaphore();
voidUnsignal();
voidSignal();
};

classMutex
{
public:
WaitMutex();
ReleaseMutex();
};
//----------------------------------------------------


//1.确定使用信号量,而非互斥量,保证并行操作
//2.当缓冲区并不满并且下载没结束时,下载线程运行
//3.当缓冲区并不空并且下载没结束时,存储线程运行


#defineMAX_COUNT1000
//缓冲区数组,模拟循环队列
Blockg_Buffer[MAX_COUNT];
Threadg_Download(ProcA);
Threadg_Write(ProcB);

//一开始缓冲区空间为MAX_COUNT,整个缓冲区可供下载的数据填充
SemaphoreForDownload(MAX_COUNT,MAX_COUNT);
//一开始缓冲区无数据可供存储
SemaphoreForWrite(0,MAX_COUNT);

//下载任务是否完成
boolisDone;
//下载的数据从缓冲区的哪个地方开始填充
intin_index;
//存储的数据从缓冲区的哪个地方开始提取
intout_index;

voidProcA()
{
while(true)
{
//首先取得一个空闲空间,以便下载数据填充
ForDownload.Unsignal();
//填充
isDone=GetBlockFromNet(g_Buffer+in_index);
//更新索引
in_index=(in_index+1)%MAX_COUNT;
//提示存储线程可以工作
ForWrite.Signal();

//当任务全部下载完成,进程就可以结束了
if(isDone)
break;
}
}

voidProcB()
{
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;
}
}

intmain()
{
isDone=false;
in_index=0;
out_index=0;
g_Download.Start();
g_Write.Start();
}

 



相关评论