简介本文向大家介绍一个C++实战项目:C++11实现多线程下载操作类,很多时候我们需要同时在网络上下载文件,那么就需要一个类来管理多线程下载,提高下载速度,具有一定的C++实战价值,感兴趣的朋友可以参考一下。
先看个简单例子
#include <iostream>
#include <string>
#include <sstream> //stringstream
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
// 下载类
class Download
{
public:
Download(int id, std::string name)
: mId(id), mName(name), mFinish(false)
{
}
// 下载函数
void operator()() // void operator()() const
{
while (!mFinish)
{
std::lock_guard<std::mutex> lock(mMutex);
std::cout << "线程" << mId << " 正在下载... " << std::endl;
// 假如3s下载完成
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "线程" << mId << " 下载完成... " << std::endl;
mFinish = true;
}
}
private:
int mId;
std::string mName;
bool mFinish;
static std::mutex mMutex;
};
std::mutex Download::mMutex;
int main()
{
int n = 10;
std::vector<std::thread> thread;
for (int i = 0; i < n; ++i)
{
std::stringstream ss;
ss << "名称 " << i << " 线程";
thread.push_back(std::thread{ Download(i,ss.str()) });
}
for (auto& t : thread)
{
t.join();
}
return 0;
}
输出
加入暂停及继续功能
#include <iostream>
#include <string>
#include <sstream> //stringstream
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
// 下载类
class CDownload
{
public:
CDownload() = delete;
CDownload(int id, std::string name)
: mId(id), mName(name)
{
mIsPause = false;
mIsFinish = false;
}
CDownload(const CDownload& src)
{
//std::cout << "copy..." << std::endl;
mId = src.mId;
mName = src.mName;
mIsPause = false;
mIsFinish = false;
}
~CDownload()
{
if (mThread.joinable())
{
mThread.join();
}
}
// 线程启动
void Run()
{
mThread = std::thread{ &CDownload::ProcessEntries,this };
}
// 下载函数
void ProcessEntries()
{
while (!mIsFinish)
{
//std::lock_guard<std::mutex> lock(mMutex);
if (mIsPause)
{
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "线程" << mId << " 正在暂停... " << std::endl;
}
else
{
std::cout << "线程" << mId << " 正在下载... " << std::endl;
// 假如5s下载完成
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "线程" << mId << " 下载完成... " << std::endl;
mIsFinish = true;
}
}
}
// 暂停
void Pause() { mIsPause = true; }
// 唤醒
void Resume() { mIsPause = false; }
private:
int mId;
std::string mName;
bool mIsPause;
bool mIsFinish;
std::thread mThread;
static std::mutex mMutex;
};
std::mutex CDownload::mMutex;
int main()
{
int n = 10;
std::vector<CDownload> thread;
for (int i = 0; i < n; ++i)
{
std::stringstream ss;
ss << " 线程" << i << "名称";
//CDownload Download(i, ss.str());
thread.push_back(std::move(CDownload{ i, ss.str() }));
// 这里有个特别值得注意的地方:此时vector内存不够 需要扩大内存,重新分配内存 这时再调用拷贝构造函数将Download拷贝到新的内存
}
// 启动线程
for (auto& t : thread)
{
t.Run();
}
//// 暂定指定线程
//std::this_thread::sleep_for(std::chrono::seconds(4));
//thread[1].Pause();
//// 唤醒指定线程
//std::this_thread::sleep_for(std::chrono::seconds(4));
//thread[1].Resume();
// 全部暂停
std::this_thread::sleep_for(std::chrono::seconds(4));
for (auto& t : thread)
{
t.Pause();
}
// 全部开始
std::this_thread::sleep_for(std::chrono::seconds(4));
for (auto& t : thread)
{
t.Resume();
}
return 0;
}
输出
备注:因为示例程序线程没有做同步处理,这里是为了模拟多线程下载,对于std::cout函数不做同步处理,所以才出现打印顺序错乱的现象。
增加一个下载管理类
#include <iostream>
#include <string>
#include <sstream> //stringstream
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
#include <exception>
// 下载类
class CDownload
{
public:
CDownload() = delete;
CDownload(int id, std::string& name)
: mId(id), mName(name)
{
mIsPause = false;
mIsFinish = false;
}
CDownload(const CDownload& src)
{
//std::cout << "copy..." << std::endl;
mId = src.mId;
mName = src.mName;
mIsPause = false;
mIsFinish = false;
}
~CDownload()
{
if (mThread.joinable())
{
mThread.join();
}
}
// 线程启动
void Run()
{
mThread = std::thread{ &CDownload::ProcessEntries,this };
}
// 下载函数
void ProcessEntries()
{
while (!mIsFinish)
{
//std::lock_guard<std::mutex> lock(mMutex);
if (mIsPause)
{
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "线程" << mId << " 正在暂停... " << std::endl;
}
else
{
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "线程" << mId << " 正在下载... " << std::endl;
// 假如3s下载完成
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "线程" << mId << " 下载完成... " << std::endl;
mIsFinish = true;
}
}
}
// 暂停
void Pause() { mIsPause = true; }
// 唤醒
void Resume() { mIsPause = false; }
private:
int mId;
std::string mName;
bool mIsPause;
bool mIsFinish;
std::thread mThread;
static std::mutex mMutex;
};
std::mutex CDownload::mMutex;
// 下载管理类
class CDownloadMgr
{
public:
CDownloadMgr() {}
~CDownloadMgr() {}
// 创建新下载
void CreateDownload(CDownload& NewDownload)
{
mVthread.push_back(NewDownload);
(mVthread.end() - 1)->Run();
}
// 创建新下载
void CreateDownload(int id, std::string& name)
{
CDownload Download(id, name);
mVthread.push_back(Download);
(mVthread.end() - 1)->Run();
}
// 暂定指定线程
void PauseOne(int nIndex)
{
if (nIndex >= mVthread.size())
throw std::runtime_error("暂定指定线程出错");
mVthread.at(nIndex).Pause();
}
// 唤醒指定线程
void ResumeOne(int nIndex)
{
if (nIndex >= mVthread.size())
throw std::runtime_error("唤醒指定线程出错");
mVthread.at(nIndex).Resume();
}
// 全部暂停
void PauseALL()
{
for (auto& t : mVthread)
{
t.Pause();
}
}
// 全部开始
void StartALL()
{
for (auto& t : mVthread)
{
t.Resume();
}
}
private:
std::vector<CDownload> mVthread;
};
int main()
{
CDownloadMgr DownloadMgr;
int n = 10;
for (int i = 0; i < n; ++i)
{
std::stringstream ss;
ss << " 线程" << i << "名称";
DownloadMgr.CreateDownload(i, ss.str());
}
return 0;
}
输出
本文向大家介绍一个C++实战项目:基于Duilib的CEF3中C++与JS函数互相调用示例,主要涉及开发技术点为DuiLib界面开发、谷歌浏览器CEF插件开发、C++与JavaScript的相互调用,具有一定的C++实战价值,感兴趣的朋友可以参考一下。
OpenMP是一种用于共享内存并行系统的多线程程序设计方案,本文向大家介绍C++并行计算之OpenMP快速入门,感兴趣的朋友可以参考一下。
一般好的软件程序是不应该占用太多CPU时间和内存空间的,一般在自己的学习过程中,我们常常忽略这一点,虽然功能实现没有问题,但是程序占用太多CPU时间,这在实际开发中是不允许的,一个好的程序员也应该注意这个问题。本文就CPU使用率问题做一些简单介绍,为开发稳定健壮的程序提供参考。
本文向大家介绍一个C++实战项目:C++实现MD5、DES加密,主要涉及MD5加密、DES加解密算法,具有一定的C++实战价值,感兴趣的朋友可以参考一下。
本文向大家介绍一个C++实战项目:C++程序崩溃生成Dump文件。在程序运行时候崩溃是头疼的时,本实战项目可在程序运行崩溃时在程序目录下生成Dump文件,具有一定的C++实战价值,感兴趣的朋友可以参考一下。
本文向大家介绍一个C++实战项目:C++制作一个简单的程序依赖DLL打包工具,有时候我们需要对某个程序进行打包,却不知道该程序依赖哪些动态库,这个工具可实现程序的一键打包功能,具有一定的C++实战价值,感兴趣的朋友可以参考一下。