【本文链接】

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.当缓冲区并不空并且下载没结束时,存储线程运行

//缓冲区数组,模拟循环队列
Block g_Buffer[MAX_COUNT];
Thread g_Download(ProcA);
Thread g_Write(ProcB);

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

//下载任务是否完成
bool isDone;
//下载的数据从缓冲区的哪个地方开始填充
int in_index;
//存储的数据从缓冲区的哪个地方开始提取
int out_index;

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

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

void ProcB()
{
    while(true)
    {
        //查询时候有数据可供存储
        ForWrite.Unsignal();
        //存储
        WriteBlockToDisk(g_Buffer + out_index);
        //更新索引
) % MAX_COUNT;
        //将空闲空间还给缓冲区
        ForDownload.Signal();

//当任务全部下载完成,并且所有的数据都存储到硬盘中,进程才可以结束
        if(isDone && in_index == out_index)
            break;
    }
}

int main()
{
    isDone = false;
    in_index = ;
    out_index = ;
    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.10 编程之美-双线程下载[double threads to download]的更多相关文章

  1. Java并发编程:4种线程池和缓冲队列BlockingQueue

    一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池.使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动 ...

  2. java并发编程之美-阅读记录1

    1.1什么是线程? 在理解线程之前先要明白什么是进程,因为线程是进程中的一个实体.(线程是不会独立存在的) 进程:是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,线程则是进程中的 ...

  3. 原创】Java并发编程系列2:线程概念与基础操作

    [原创]Java并发编程系列2:线程概念与基础操作 伟大的理想只有经过忘我的斗争和牺牲才能胜利实现. 本篇为[Dali王的技术博客]Java并发编程系列第二篇,讲讲有关线程的那些事儿.主要内容是如下这 ...

  4. 理解微信小程序的双线程模型

    有过微信小程序开发经验的朋友应该都知道"双线程模型"这个概念,本文简单梳理一下双线程模型的一些科普知识,学识浅薄,若有错误欢迎指正. 我以前就职于「小程序·云开发」团队,在对外的一 ...

  5. 【特别推荐】10款唯美浪漫的婚礼 & 结婚纪念网站模板

    互联网的重要性不言而喻,如今我们的生活已经完全离不开网络.这里给大家分享一组唯美浪漫的结婚邀请网站以及婚礼请柬网站模板,如果你也正想制作这样的网站,相信这些漂亮的网站模板能够带给你很大的帮助,让你快速 ...

  6. 【编程之美】CPU

    今天开始看编程之美 .第一个问题是CPU的使用率控制,微软的问题果然高大上,我一看就傻了,啥也不知道.没追求直接看答案试了一下.发现自己电脑太好了,4核8线程,程序乱飘.加了一个进程绑定,可以控制一个 ...

  7. 编程之美_1.1 让CPU占用率曲线听你指挥

    听到有人说让要写一个程序,让用户来决定Windows任务管理器的CPU占用率. 觉得很好奇.但第一个想法就是写个死循环.哈哈.不知道具体的占用率是多少,但至少能保证在程序运行时,CPU的占用率终会稳定 ...

  8. Java 集合深入理解(10):Deque 双端队列

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 什么是 Deque Deque 是 Double ended queue (双端队列) 的缩写,读音和 deck 一样,蛋 ...

  9. 编程之美之数独求解器的C++实现方法

    编程之美的第一章的第15节.讲的是构造数独.一開始拿到这个问题的确没有思路, 只是看了书中的介绍之后, 发现原来这个的求解思路和N皇后问题是一致的. 可是不知道为啥,反正一開始确实没有想到这个回溯法. ...

随机推荐

  1. ovs-agent流程

    1. 代码流程分析 neutron/plugins/openvswitch/agent/ovs_neutron_agent.py:main() plugin = OVSNeutronAgent(**a ...

  2. Mysql-提示java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 7 to TIMESTAMP.

    在Mysql数据库中使用DATETIME类型来存储时间,使用JDBC中读取这个字段的时候,应该使用 ResultSet.getTimestamp(),这样会得到一个java.sql.Timestamp ...

  3. Java-try-catch-finally

    try-catch语句还可以包括第三部分,就是finally子句.它表示无论是否出现异常,都应当执行的内容.try-catch-finally语句的一般语法形式为: try { // 可能会发生异常的 ...

  4. python 学习笔记1(序列;if/for/while;函数;类)

    本系列为一个博客的学习笔记,一部分为我原创. 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 1. print 可以打印 有时需要 ...

  5. Linux Systemcall By INT 0x80、Llinux Kernel Debug Based On Sourcecode

    目录 . 系统调用简介 . 系统调用跟踪调试 . 系统调用内核源码分析 1. 系统调用简介 关于系统调用的基本原理,请参阅另一篇文章,本文的主要目标是从内核源代码的角度来学习一下系统调用在底层的内核中 ...

  6. tomcat7禁用catalina.out输出

    tomcat7中禁用catalina.out的输出,又可能很大. 直接修改catalina.sh文件的输出语句. 在文件中找到以下内容. if [ -z "$CATALINA_OUT&quo ...

  7. 统计网站访问量,以GD2库图像形式输出

    index.php页面<?php session_start(); if($_SESSION[temp]==""){ //判断$_SESSION[temp]=="& ...

  8. iframe 动态onload事件处理方式

    转自:http://w3help.org/zh-cn/causes/SD9022 标准参考 关于 HTML 4.01 规范中 BODY 标记的 onload 属性说明: http://www.w3.o ...

  9. hdu 1241 Oil Deposits(水一发,自我的DFS)

    解题思路: 1. 遍历扫描二维数组,遇到‘@’,结果ans++; 2. 将当前 i,j 位置置为‘*’,将当前‘@’的 i,j 传人到DFS函数中,开始遍历八个方向的字符 如果碰到 '@' 则先将当前 ...

  10. hdu 2047 阿牛的EOF牛肉串

    如果末尾加的是E或F,显然是2*a[i-1] 如果末尾加的是O,则末2位一定是EO或FO,则为2*a[i-2]. 然后两者相加 2*a[i-1]+2*a[i-2] = 2*(a[i-1]+a[i-2] ...