C++11实现多线程下载操作类

2023-03-16 11:07:36 2679人已围观 26已点赞 14人已收藏

简介本文向大家介绍一个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;
}

输出

C++多线程下载,线程相关

加入暂停及继续功能

#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;
}

输出

C++多线程下载,线程相关

备注:因为示例程序线程没有做同步处理,这里是为了模拟多线程下载,对于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++多线程下载,线程相关

源码下载
  • 最近更新:   2022-06-22开发环境:   Visual Studio 2015
  • 源码大小:   1.73KB下载次数:  21 

更多为你推荐