C++11 线程池

2022/3/9 22:14:44

本文主要是介绍C++11 线程池,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在这里插入图片描述

cpp

#include<thread>
#include<mutex>
#include<vector>
#include<condition_variable>
#include<boost/circular_buffer.hpp>
#include<functional>
#include<atomic>
#include<cassert>


class ThreadPool
{
public:
	explicit ThreadPool(size_t n) :q_{ n }, running_{ false }{}
	~ThreadPool()
	{
		Stop();
	}
	void Start(size_t n)
	{
		if (running_)return;
		running_ = true;
		threads_.reserve(n);
		while (n--)
		{
			threads_.emplace_back(&ThreadPool::Worker, this);
		}
	}
	template<typename Fun>
	void submit(Fun f)
	{
		std::unique_lock<std::mutex> lk{ mtx_ };
		not_full_.wait(lk, [this] {return !running_ || !q_.full(); });
		assert(!running_||!q_.full());
		if (!running_) return;
		q_.push_back(std::move(f));
		not_empty_.notify_one();
	}
	void Stop()
	{
		if (!running_)return;;
		running_ = false;
		not_full_.notify_all();
		not_empty_.notify_all();
		for (auto& th : threads_)
		{
			if (th.joinable())th.join();
		}
	}

private:
	void Worker()
	{
		while (true)
		{
			task t;
			{
				std::unique_lock<std::mutex> lk{ mtx_ };
				not_empty_.wait(lk, [this] {return !running_ || !q_.empty(); });
				assert(!running_ || !q_.empty());
				if (!running_)return;
				t =  std::move(q_.front()) ;
				q_.pop_front();
				not_full_.notify_one();
			}
			t();
		}
	}
private:
	using task = std::function<void()>;
	std::vector<std::thread>threads_;
	boost::circular_buffer<task>q_;
	std::mutex mtx_;
	std::condition_variable not_full_;
	std::condition_variable not_empty_;
	std::atomic<bool> running_;
};

#include<iostream>
int main()
{
	ThreadPool pool{ 8 };
	std::mutex mtx;
	pool.Start(4);
	for (int i = 0; i < 100; ++i)
	{
		pool.submit(
			[i]{
				std::cout << i << " " << std::this_thread::get_id() << std::endl;
			});
	}
	return 0;
}

可传参带返回值的

#include <vector>
#include <thread>
#include <boost/circular_buffer.hpp>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <future>
#include <atomic>

class task {
public:
	task() = default;

	template <class Fun>
	explicit task(Fun&& f) : ptr_{ new wrapper{ std::move(f) } } {}

	void operator()() { ptr_->call(); }

private:
	class wrapper_base {
	public:
		virtual void call() = 0;
		virtual ~wrapper_base() = default;
	};

	template <class Fun>
	class wrapper : public wrapper_base {
	public:
		explicit wrapper(Fun&& f) : f_{ std::move(f) } {}
		virtual void call() override { f_(); }

	private:
		Fun f_;
	};

	std::unique_ptr<wrapper_base> ptr_;
};

class thread_pool {
public:
	explicit thread_pool(size_t n) : q_{ n }, running_{ false } {}

	~thread_pool() { stop(); }

	void start(size_t n) {

		if (running_) return;

		running_ = true;
		threads_.reserve(n);
		while (n--) {
			threads_.emplace_back(&thread_pool::worker, this);
		}
	}

	void stop() {

		if (!running_) return;
		running_ = false;
		not_full_.notify_all();
		not_empty_.notify_all();

		for (auto& t : threads_) {
			if (t.joinable()) t.join();
		}
	}

	template <class Fun,typename ...Args>
	auto submit(Fun&& f,Args&&...args)->std::future<decltype(f(args...))> {

		using RetType = decltype(f(args...));
		auto pt = std::make_unique<std::packaged_task<RetType()>>( std::bind(std::forward<Fun>(f), std::forward<Args>(args)...) );
		auto ret = pt->get_future();
		task t{ std::move(*pt) };

		{
			std::unique_lock lk{ m_ };
			not_full_.wait(lk, [this] { return !running_ || !q_.full(); });

			assert(!running_ || !q_.full());

			if (!running_) return {};

			q_.push_back(std::move(t));
			not_empty_.notify_one();
		}

		return ret;
	}

private:
	void worker() {

		while (true) {

			task t;
			{
				std::unique_lock lk{ m_ };
				not_empty_.wait(lk, [this] { return !running_ || !q_.empty(); });

				assert(!running_ || !q_.empty());

				if (!running_) return;

				t = std::move(q_.front());
				q_.pop_front();
				not_full_.notify_one();
			}
			t();
		}
	}

	std::vector<std::thread> threads_;
	boost::circular_buffer<task> q_;
	std::mutex m_;
	std::condition_variable not_full_;
	std::condition_variable not_empty_;
	std::atomic<bool> running_;
};

#include <iostream>
int func(int a)
{
	std::cout << "id:" << std::this_thread::get_id() << std::endl;
	return a;
}

int main() {

	thread_pool pool{ 10 };
	pool.start(3);
	std::vector<std::future<int>> rets;
	for (int i = 0; i < 100; i++) {
		auto ret = pool.submit(func, i);
		rets.push_back(std::move(ret));
	}
	for (auto& ret : rets) {
		std::cout << ret.get() << " ";
	}
}


这篇关于C++11 线程池的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程