共享vps可以做网站吗,小程序的定义,金阳龙泉苑网站建设,上海门户网站制TOC
介绍 std::future 是C11标准库中的一个模板类#xff0c;他表示一个异步操作的结果#xff0c;当我们在多线程编程中使用异步任务时#xff0c;std::future可以帮助我们在需要的时候#xff0c;获取任务的执行结果#xff0c;std::future 的一个重要特性是能…TOC
介绍 std::future 是C11标准库中的一个模板类他表示一个异步操作的结果当我们在多线程编程中使用异步任务时std::future可以帮助我们在需要的时候获取任务的执行结果std::future 的一个重要特性是能够阻塞当前线程直到异步操作完成从而确保我们在获取结果时不会遇到未完成的操作。
应用场景
异步任务当我们需要在后台执行一些耗时操作时如网络请求或计算密集型任务等std::future可以用来表示这些异步任务的结果通过将任务与主线程分离我们可以实现任务的并行操作从而提高程序的执行效率并发操作在多线程编程中我们可能需要等待某些任务完成后才能执行其他操作通过使用std::future,我们可以实现线程之间的同步确保任务完成后再获取结果并继续执行后续结果结果获取std::future提供了一种安全的方式来获取异步任务的结果。我们可以使用std::future::get()函数来获取任务的结果此函数会阻塞当前线程直到异步操作完成。这样在调用get()函数时我们可以确保已经获取到了所需的结果
使用方法
std::async std::async是一种将任务与std::future关联的简单方法它创建并运行一个异步任务并返回一个与该任务结果关联的std::future对象。默认情况下std::async是否启动了一个新的线程或者在等待future时任务是否同步运行取决于你给的参数这个参数为std::launch类型
std::launch::deferred 表明该函数会被延迟调用直到在future上调用get()或者wait()才会开始执行任务std::launch::async表明函数会在自己创建的线程上运行std::launch::deferred | std::launch::async 内部通过系统等条件自动选择策略
#include iostream
#include future
#include thread
#include chronousing namespace std;int async_task()
{std::this_thread::sleep_for(std::chrono::seconds(2));return 2;
}int main()
{// 关联异步任务async_task 和 futurestd::futureint result std::async(std::launch::deferred | std::launch::async, async_task);// 此时可以执行其他操作cout 干其他事情 endl;// 获取异步任务结果int ret result.get();cout ret endl;return 0;
}
std::packaged_task std::packaged_task就是将任务和std::future绑定在一起的模板是一种对任务的封装我们可以通过std::packaged_task对象获取任务相关联的std::future对象通过调用get_future()方法获取。std::packaged_task的模板参数是函数签名。
所谓函数签名就是一个函数头去掉函数名
下面介绍一下std::packaged_task首先这个类型的对象是不可复制的 可以看到拷贝构造函数被delete了。 std::packaged_task是用来包装异步任务的工具它的本质是将一个可调用对象封装起来和std::future结合起来这个不能被直接调用因为这样的实质是同步调用任务而不是异步调用并且std::packaged_task对象是没有返回值的因为是不可拷贝的 所以std::packaged_task对象在使用的时候需要创建一个线程然后使用智能指针或者move函数来进行传递。注意因为创建了一个新的线程并且需要获取到这个新的线程执行任务的结果所以我们就需要进行等待或者分离即join和detach()。
使用move进行移动
#include iostream
#include future
#include thread
#include memory
#include chronoint Add(int num1, int num2)
{std::this_thread::sleep_for(std::chrono::seconds(2));return num1 num2;
}int main()
{std::packaged_taskint(int, int) task(Add);std::futureint fu task.get_future();std::thread th(std::move(task), 11, 22);int ret fu.get();std::cout ret std::endl;th.join();return 0;
}
使用智能指针
#include iostream
#include future
#include thread
#include memory
#include chronoint Add(int num1, int num2)
{std::this_thread::sleep_for(std::chrono::seconds(2));return num1 num2;
}int main()
{auto ptask std::make_sharedstd::packaged_taskint(int, int)(Add);std::futureint fu ptask-get_future();std::thread th([ptask](){(*ptask)(11, 22);});int ret fu.get();std::cout ret std::endl;th.join();return 0;
}
std::promise std::promise提供了一种设置值的方式它可以在设置之后通过相关联的std::future对象进行读取换种说法来说就是之前说过的std::future可以读取一个异步函数的返回值了但是要等待就绪而std::promise就提供了一个方式手动让std::future就绪
#include iostream
#include future
#include chronovoid task(std::promiseint result_promise)
{int result 2;result_promise.set_value(result);std::cout result std::endl;
}int main()
{std::promiseint result;std::futureint reuslt_future result.get_future();std::thread th(task, std::move(result));int ret reuslt_future.get();std::cout ret std::endl;th.join();return 0;
}
线程池设计
#include iostream
#include functional
#include memory
#include thread
#include future
#include mutex
#include condition_variable
#include vectorclass threadPool
{
public:using ptr std::shared_ptrthreadPool;using Functor std::functionvoid(void);threadPool(int thr_count 1): _stop(false){for (int i 0; i thr_count; i){_threads.emplace_back(threadPool::entry, this);}}~threadPool(){stop();}// push传入的是首先有一个函数--用户要执行的函数接下来是不定参标识要处理的数据就是要传入到函数中的参数// push函数内部会将这个传入的函数封装成一个异步任务packaged_task// 使用 lambda 生成一个可调用对象内部执行异步程序抛入到任务池中由工作线程取出进行执行template typename F, typename ...Argsauto push(F func, Args ...args) - std::futuredecltype(func(args...)){// 1. 将传入的函数封装成一个packaged_task任务using return_type decltype(func(args...));auto tmp_func std::bind(std::forwardF(func), std::forwardArgs(args)...);//auto task std::make_sharedstd::packaged_taskreturn_type(std::forwardArgs(args)...)(std::forward(func));auto task std::make_sharedstd::packaged_taskreturn_type()(tmp_func);std::futurereturn_type fu task-get_future();// 2. 构造一个lambda 匿名函数捕获任务对象函数内执行任务对象{std::unique_lockstd::mutex lock(_mutex);// 3. 将构造出来的匿名函数抛入到任务池中_taskpool.push_back([task](){ (*task)(); });_cv.notify_one();}return fu;}void stop(){if(_stop true) return ;_stop true;_cv.notify_all();for (auto thread : _threads){thread.join();}}private:// 线程入口函数---内部不断的从任务池中取出任务进行执行void entry(){while (!_stop){std::vectorFunctor tmp_taskpool;{// 加锁std::unique_lockstd::mutex lock(_mutex);// 等待任务池不为空或者_stop 被置位返回true_cv.wait(lock, [this](){ return _stop || !_taskpool.empty(); });// 取出任务进行执行tmp_taskpool.swap(_taskpool); // 这里是将全局任务池里面的任务全部给一个线程里面的任务池 }for (auto task : tmp_taskpool){task();}}}private:std::atomicbool _stop;std::vectorFunctor _taskpool; // 任务池std::mutex _mutex; // 互斥锁std::condition_variable _cv; // 条件变量std::vectorstd::thread _threads;
};
main函数
#include threadpool.hppint Add(int num1, int num2)
{return num1 num2;
}int main()
{threadPool pool;for(int i 0; i 10; i){std::futureint fu pool.push(Add, 11, i);std::cout fu.get() std::endl;}pool.stop();return 0;
}