【编程之美】双线程高效下载

2024-04-05 01:32

本文主要是介绍【编程之美】双线程高效下载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一,题目

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

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

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

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

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

        

二,核心源码


 //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 diskbool 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 1000Block 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.chinasem.cn/article/877329

相关文章

Java下载文件中文文件名乱码的解决方案(文件名包含很多%)

《Java下载文件中文文件名乱码的解决方案(文件名包含很多%)》Java下载文件时,文件名中文乱码问题通常是由于编码不正确导致的,使用`URLEncoder.encode(filepath,UTF-8... 目录Java下载文件中文文件名乱码问题一般情况下,大家都是这样为了解决这个问题最终解决总结Java下

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

Tomcat高效部署与性能优化方式

《Tomcat高效部署与性能优化方式》本文介绍了如何高效部署Tomcat并进行性能优化,以确保Web应用的稳定运行和高效响应,高效部署包括环境准备、安装Tomcat、配置Tomcat、部署应用和启动T... 目录Tomcat高效部署与性能优化一、引言二、Tomcat高效部署三、Tomcat性能优化总结Tom

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

Python实现文件下载、Cookie以及重定向的方法代码

《Python实现文件下载、Cookie以及重定向的方法代码》本文主要介绍了如何使用Python的requests模块进行网络请求操作,涵盖了从文件下载、Cookie处理到重定向与历史请求等多个方面,... 目录前言一、下载网络文件(一)基本步骤(二)分段下载大文件(三)常见问题二、requests模块处理

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬