【c++】c++11實現執行緒池

徘徊彼岸花發表於2024-05-08
#include <iostream> 
#include <mutex>
#include <queue>
#include <vector>
#include <functional>
#include <condition_variable>
#include <atomic>
#include <chrono>

class ThreadPool
{
private:
	std::queue<std::function<void()>> m_tasks;	
	std::vector<std::thread> m_threads;			
	std::thread m_threadManagement;	

	std::condition_variable cvTasksNotEmpty;	
	std::mutex mtxTasks;
	std::mutex mtxThreads;
	std::mutex mtxPoolFields;

	bool m_shutdown;			
	int m_numMinThreads;	
	int m_numMaxThreads;	
	std::atomic<int> m_numCurThreads;		
	std::atomic<int> m_numBusyThreads;	
	std::atomic<int> m_numExitThreads;	
	const int THREADMANAGENUM = 2;	

public:
	ThreadPool(int min, int max) :m_threadManagement(ThreadPool::threadManage, this), m_numMinThreads(min < 1 ? 1 : min), m_numMaxThreads(max)
	{
		m_shutdown = false;
		m_numCurThreads = m_numMinThreads;	
		m_numBusyThreads = 0;
		m_numExitThreads = 0;

		for (int i = 0; i < m_numCurThreads; i++)
		{
			std::unique_lock<std::mutex> ulThreads(mtxThreads);
			m_threads.emplace_back([this]() {
				m_numCurThreads.fetch_add(1, std::memory_order_relaxed);
				threadTask();
				});
		}


	}
	ThreadPool(ThreadPool& another) = delete;	
	ThreadPool& operator=(ThreadPool& another) = delete;	
	~ThreadPool()
	{
		//析構銷燬執行緒池,釋放資源
		m_shutdown = true;	
		cvTasksNotEmpty.notify_all();	//執行緒池要銷燬了。通知所有執行緒全部不阻塞向下執行

		for (auto& item : m_threads)	
		{
			item.join();	//等待全部執行緒return終止
		}

		m_threadManagement.join();	//等待管理執行緒終止
	}

	//子執行緒任務
	void threadTask()
	{
		while (true)
		{
			std::unique_lock<std::mutex> ulTasks(mtxTasks);

			cvTasksNotEmpty.wait(ulTasks, [=]() {
				return !m_tasks.empty() || m_shutdown;
				});

			if (m_numExitThreads > 0)
			{
				m_numExitThreads.fetch_sub(1, std::memory_order_relaxed);
				if (m_numCurThreads > m_numMinThreads)
				{
					m_numCurThreads.fetch_sub(1, std::memory_order_relaxed);
					//關閉當前執行緒,從m_threads剔除
					for (auto iter = m_threads.begin(); iter != m_threads.end();)
					{
						if (iter->get_id() == std::this_thread::get_id())
						{
							iter->detach();
							std::unique_lock<std::mutex> ulThreads(mtxThreads);
							iter = m_threads.erase(iter);
						}
						else
						{
							iter++;
						}
					}
					return;
				}

			}

			//判斷是否執行緒池被關閉,管理者執行緒不工作時m_threads中執行緒數固定,在析構中全部join(),閒置執行緒直接return終止
			if (m_shutdown == true && m_tasks.empty())
			{
				return;
			}

			//取任務執行
			std::function<void()> task(std::move(m_tasks.front()));
			m_tasks.pop();
			std::cout << "threadID=" << std::this_thread::get_id() << ",start working..." << std::endl;
			ulTasks.unlock();	
			m_numBusyThreads.fetch_add(1, std::memory_order_relaxed);

			task();	//執行緒執行任務

			m_numBusyThreads.fetch_sub(1, std::memory_order_relaxed);
			std::cout << "threadID=" << std::this_thread::get_id() << ",end working..." << std::endl;	//執行緒執行完任務日誌輸出
		}
	}

	//主執行緒新增任務。生產者
	template<typename F, typename... Args>
	void enqueue(F&& f, Args&&... args)	
	{
		auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);	
		{
			std::unique_lock<std::mutex> ulTasks(mtxTasks);	
			m_tasks.emplace(std::move(task));		
		}
		cvTasksNotEmpty.notify_one();	
	}

	//管理者執行緒任務
	static void threadManage(ThreadPool* poolInstance);

};

void ThreadPool::threadManage(ThreadPool* poolInstance)
{
	while (!poolInstance->m_shutdown)
	{
		std::this_thread::sleep_for(std::chrono::seconds(3));

		std::unique_lock<std::mutex> ulTasks(poolInstance->mtxTasks);
		int numTasks = static_cast<int>(poolInstance->m_tasks.size());
		ulTasks.unlock();

		//加執行緒
		if (poolInstance->m_numCurThreads < poolInstance->m_numMaxThreads && poolInstance->m_numCurThreads < numTasks)
		{
			for (int i = 0; i < poolInstance->THREADMANAGENUM && poolInstance->m_numCurThreads < poolInstance->m_numMaxThreads; i++)
			{
				std::unique_lock<std::mutex> ulThreads(poolInstance->mtxThreads);
				poolInstance->m_threads.emplace_back([poolInstance]() {
					poolInstance->threadTask();
					});
			}
			poolInstance->m_numCurThreads.fetch_add(1, std::memory_order_relaxed);
		}

		//減少執行緒
		if (poolInstance->m_numBusyThreads * 2 < poolInstance->m_numCurThreads && poolInstance->m_numCurThreads > poolInstance->m_numMinThreads)
		{
			poolInstance->m_numExitThreads.store(poolInstance->THREADMANAGENUM);

			//通知m_numExitThreads個阻塞的執行緒向下執行,就會退出
			for (int i = 0; i < poolInstance->m_numExitThreads; i++)
			{
				poolInstance->cvTasksNotEmpty.notify_one();
			}
		}

	}
}


std::mutex mtxfunc;
int data = 0;
void func()
{
	for (int i = 0; i < 1000000; i++)
	{
		std::unique_lock<std::mutex> ul(mtxfunc);
		data++;
	}
}

int main()
{
	auto start1 = std::chrono::steady_clock::now();
	ThreadPool* tp = new ThreadPool(6,10);
	tp->enqueue(func);
	tp->enqueue(func);
	tp->enqueue(func);
	tp->enqueue(func);
	tp->enqueue(func);
	tp->enqueue(func);
	delete tp;
	auto end1 = std::chrono::steady_clock::now();
	std::cout << "MainThreadID=" << std::this_thread::get_id() << ", final data= " << data << std::endl;
	std::cout << "pool spend:" << std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1).count() << "ms" << std::endl;

	auto start2 = std::chrono::steady_clock::now();
	for (int i = 0; i < 6000000; i++)
	{
		data++;
	}
	auto end2 = std::chrono::steady_clock::now();
	std::cout << "mainthread spend:" << std::chrono::duration_cast<std::chrono::microseconds>(end2 - start2).count() << "ms" << std::endl;
	std::cout << "MainThreadID=" << std::this_thread::get_id() << ", final data= " << data << std::endl;

}

效率比單執行緒低的多???

相關文章