程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 1.10 編程之美-雙線程下載[double threads to download]

1.10 編程之美-雙線程下載[double threads to download]

編輯:C++入門知識

【本文鏈接】

http://www.cnblogs.com/hellogiser/p/double-threads-to-download-and-write.html

【題目】

        網絡上下載數據,然後存儲到硬盤上。簡單做法是:先下載一塊然後寫到硬盤,然後再下載,再寫到硬盤上。

        缺點:需要先下載完才能寫入硬盤,下載和寫是串行操作。

        改進:讓兩個線程並行進行,設置緩沖區,采用信號量的形式。

                    下載線程,只要緩沖區有空余就下載,下載完成之後告訴寫線程緩沖區有數據了。

                     寫線程,只要緩沖區有數據就寫入,寫完後告訴下載線程緩沖區有空閒了。

【代碼】

 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
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/7/4
*/
//---------------------API------------------------------
//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();
}

【參考】

http://www.cnblogs.com/daniagger/archive/2012/03/23/2413764.html

http://www.cnblogs.com/youxin/p/3586975.html

http://blog.csdn.net/tianshuai1111/article/details/7692213

【本文鏈接】

http://www.cnblogs.com/hellogiser/p/double-threads-to-download-and-write.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved