练习题 1: 使用 std::future
和 std::async
编写一个程序,使用 std::async
启动一个异步任务,该任务计算两个整数的和。主线程等待任务完成并输出结果。
题目要求:
-
使用
std::async
创建异步任务。 -
主线程获取任务的结果并打印。
#include<iostream>
#include<future>
#include<thread>
using namespace std;
int compute_sum(int x, int y) {
cout << "子线程开始计算.." << endl;
return x + y;
}
int main() {
cout << "主线程开始..." << endl;
int x = 1, y = 2;
future<int> fut = async(launch::async, compute_sum, x, y);
int result = fut.get();
cout << "主线程得到答案:" << result << endl;
return 0;
}
练习题 2: 使用 std::shared_future
编写一个程序,创建一个异步任务,计算一个整数的平方,并使用 std::shared_future
在多个线程中共享计算结果。
题目要求:
-
使用
std::async
启动一个计算平方的任务。 -
使用
std::shared_future
在多个线程中共享该结果。 -
每个线程打印结果。
#include<iostream>
#include<future>
#include<thread>
#include<vector>
#include<mutex>
using namespace std;
mutex mtx;
int compute_sqr(int x) {
lock_guard<mutex> lock(mtx);
cout << "现在正在计算的线程是:" << this_thread::get_id() << endl;
return x * x;
}
int main() {
cout << "主线程开始..." << endl;
future<int> fut = async(launch::async, compute_sqr, 5);
shared_future<int> shared_fut = fut.share();
vector<thread> threads;
for (int i = 0; i < 3; i++) {
threads.push_back(thread([&shared_fut] {
lock_guard<mutex> lock(mtx);
cout << "现在运行的线程是:" << this_thread::get_id() << " 获得sqr=" << shared_fut.get() << endl;
}));
}
for (auto& t : threads) {
t.join();
}
cout << "主线程结束" << endl;
return 0;
}
这里对于shared_future的理解更加深刻了,async线程只会运行一次,shared_future使得结果可以让不同线程多次获取
练习题 3: 使用 std::packaged_task
和 std::thread
编写一个程序,使用 std::packaged_task
包装一个函数,该函数计算给定整数的阶乘。使用 std::thread
来执行任务,并获取结果。
题目要求:
-
使用
std::packaged_task
包装一个计算阶乘的函数。 -
使用
std::thread
来执行这些任务。 -
获取并打印结果。
使用ref,引用传递,需要注意的就是资源是否会释放问题,这里使用的get,join都是阻塞,所以不会有问题
#include<iostream>
#include<future>
#include<thread>
using namespace std;
mutex mtx;
int compute_factor(int x) {
int res = 1;
for (int i = 1; i <= x; i++)res *= i;
return res;
}
int main() {
cout << "主线程开始..." << endl;
packaged_task<int(int)> task(compute_factor);
int x = 5;
thread t(ref(task), x);
future<int> fut = task.get_future();
cout << x << "的阶乘=" << fut.get() << endl;
t.join();
cout << "主线程结束" << endl;
return 0;
}
使用move,要在thread移动前获取task.get_future,否则task资源已经被转移了,无法获取
#include<iostream>
#include<future>
#include<thread>
using namespace std;
int compute_factor(int x) {
int result = 1;
for (int i = 1; i <= x; ++i) {
result *= i;
}
return result;
}
int main() {
cout << "主线程开始..." << endl;
packaged_task<int(int)> task(compute_factor);
future<int> fut = task.get_future();
int x = 5;
thread t(move(task), x);
cout << x << "的阶乘=" << fut.get() << endl;
t.join();
cout << "主线程结束" << endl;
return 0;
}
练习题 4: 使用 std::promise
和 std::future
编写一个程序,使用 std::promise
和 std::future
在两个线程之间传递数据。一个线程将结果设置到 promise
中,另一个线程获取结果。
题目要求:
-
创建一个
std::promise
对象。 -
在一个线程中使用
set_value
设置结果。 -
在另一个线程中使用
future.get()
获取并打印结果。
引用版本
#include<iostream>
#include<future>
#include<thread>
#include<vector>
using namespace std;
int compute_add(promise<int>& pro,int x,int y) {
int res = x + y;
pro.set_value(res);
cout << "和线程" << this_thread::get_id() << " 计算结果=" << res << endl;
return res;
}
int compute_sqr(int x) {
int res = x * x;
cout << "平方线程" << this_thread::get_id() << " 计算结果=" << res << endl;
return res;
}
int main() {
cout << "主线程开始..." << endl;
promise<int> pro;
thread t1(compute_add, ref(pro), 3, 4);
future<int> fut = pro.get_future();
thread t2(compute_sqr, fut.get());
t1.join();
t2.join();
cout << "主线程结束" << endl;
return 0;
}
移动版本
-
promise<int>&& pro
的移动:通过move(pro)
,将promise
移动到t1
线程中。这确保了在加法线程计算后,promise
的值会被正确设置。 -
将
future
传递到线程中:compute_sqr
函数现在接收future<int>& fut
,并在里面调用fut.get()
获取加法结果。这样就不需要在主线程中调用fut.get()
,避免了重复调用get()
的问题。
#include<iostream>
#include<future>
#include<thread>
#include<vector>
using namespace std;
int compute_add(promise<int>&& pro, int x, int y) {
int res = x + y;
pro.set_value(res);
cout << "和线程 " << this_thread::get_id() << " 计算结果=" << res << endl;
return res;
}
int compute_sqr(future<int>& fut) {
int res = fut.get(); // 获取加法结果并计算平方
cout << "平方线程 " << this_thread::get_id() << " 计算结果=" << res * res << endl;
return res * res;
}
int main() {
cout << "主线程开始..." << endl;
promise<int> pro;
future<int> fut = pro.get_future(); // 获取与 promise 相关的 future
thread t1(compute_add, move(pro), 3, 4); // 将 promise 移动到线程中
thread t2(compute_sqr, ref(fut)); // 将 future 传递给平方线程
t1.join();
t2.join();
cout << "主线程结束" << endl;
return 0;
}
练习题 5: 任务队列与 std::packaged_task
创建一个任务队列,队列中的每个任务计算不同的整数的平方。使用 std::packaged_task
将每个计算包装成任务,并使用线程池执行这些任务。最终获取并输出所有任务的结果。
题目要求:
-
使用
std::packaged_task
创建多个任务,每个任务计算不同整数的平方。 -
将任务存储在容器中,并使用线程池来执行。
-
最终收集并输出每个任务的结果。
#include<iostream>
#include<future>
#include<thread>
#include<vector>
using namespace std;
int compute_sqr(int x) {
int res = x * x;
return res;
}
int main() {
cout << "主线程开始..." << endl;
vector<packaged_task<int(int)>> tasks;
vector<future<int>> futures;
for (int i = 0; i < 10; i++) {
tasks.push_back(packaged_task(compute_sqr));
futures.push_back(tasks[i].get_future());
}
vector<thread> threads;
for (int i = 0; i < 10; i++) {
threads.push_back(thread(move(tasks[i]),i+1));
}
for (auto& fut : futures) {
cout << fut.get() << endl;
}
for (auto& t : threads) {
t.join();
}
cout << "主线程结束" << endl;
return 0;
}
练习题 6: 使用 std::future
和超时
编写一个程序,使用 std::future
启动一个异步任务,计算一个大数的平方,主线程在 1 秒钟后检查任务是否完成。如果任务未完成,则打印 “任务超时”。
题目要求:
-
启动一个计算大数平方的异步任务。
-
使用
std::future::wait_for
设置超时,如果任务未在超时时间内完成,则打印 “任务超时”。
#include<iostream>
#include<future>
#include<thread>
#include<vector>
using namespace std;
int compute_sqr(int x) {
this_thread::sleep_for(2s);
int res = x * x;
return res;
}
int main() {
cout << "主线程开始..." << endl;
future<int> fut = async(launch::async, compute_sqr, 5);
future_status fut_status = fut.wait_for(1s);
if (fut_status == future_status::timeout) {
cout << "任务超时" << endl;
}
else {
cout << "任务完成,结果=" << fut.get() << endl;
}
cout << "主线程结束" << endl;
return 0;
}
练习题 7: 使用 std::future
和异常处理
编写一个程序,使用 std::async
启动一个异步任务,该任务计算一个数字的倒数。如果输入为零,则抛出异常并在主线程中捕获该异常。
题目要求:
-
使用
std::async
启动异步任务计算倒数。 -
如果输入为零,则抛出异常。
-
在主线程中捕获并打印异常信息。
#include<iostream>
#include<future>
#include<thread>
#include<vector>
using namespace std;
double compute_reciprocal(double x) {
if (x == 0)throw invalid_argument("倒数不能为0!");
return 1.0 / x;
}
int main() {
cout << "主线程开始..." << endl;
double x = 0;
future<double> fut = async(launch::async, compute_reciprocal, x);
try {
cout << x << "的倒数是" << fut.get() << endl;
}catch(const invalid_argument &e){
cout << e.what() << endl;
}
cout << "主线程结束" << endl;
return 0;
}
练习题 8: 使用 std::shared_future
和多个线程
编写一个程序,启动一个异步任务,计算 100 到 200 之间所有数字的和。多个线程使用 std::shared_future
获取该任务的结果并输出结果。
题目要求:
-
使用
std::async
启动异步任务,计算和。 -
使用
std::shared_future
将结果共享给多个线程。 -
每个线程输出结果。
#include<iostream>
#include<future>
#include<thread>
#include<vector>
using namespace std;
int compute_sum() {
int res = 0;
for (int i = 100; i <= 200; i++)res += i;
return res;
}
int main() {
cout << "主线程开始..." << endl;
future<int> fut = async(launch::async, compute_sum);
shared_future<int> shared_fut = fut.share();
vector<thread> threads;
for (int i = 0; i < 5; i++) {
threads.push_back(thread([&shared_fut] {cout << "线程" << this_thread::get_id() << "拿到共享结果为=" << shared_fut.get() << endl; }));
}
for (auto& t : threads) {
t.join();
}
cout << "主线程结束" << endl;
return 0;
}
练习题 9: 使用 std::packaged_task
和多线程计算任务
编写一个程序,创建一个 std::packaged_task
对象,包装一个计算两个整数最大公约数(GCD)的函数。然后使用多个线程分别计算不同整数对的 GCD,获取结果并输出。
题目要求:
-
使用
std::packaged_task
包装计算 GCD 的任务。 -
使用多个线程计算不同整数对的 GCD。
-
输出每对整数的 GCD 结果。
#include<iostream>
#include<future>
#include<thread>
#include<vector>
using namespace std;
int compute_gcd(int a, int b) {
return b == 0 ? a : compute_gcd(b, a % b);
}
int main() {
cout << "主线程开始..." << endl;
vector<thread> threads;
vector<future<int>> futures;
// 直接在循环中创建任务并传递给线程
for (int i = 0; i < 5; i++) {
packaged_task<int(int, int)> task(compute_gcd);
futures.push_back(task.get_future());
threads.push_back(thread(move(task), i * 10, i * 5));
}
// 等待所有线程并获取结果
for (auto& fut : futures) {
cout << "公约数为=" << fut.get() << endl;
}
// 等待所有线程完成
for (auto& t : threads) {
t.join();
}
cout << "主线程结束" << endl;
return 0;
}
练习题 10: 使用 std::promise
实现任务通知
编写一个程序,创建一个 std::promise
对象,主线程通过 promise
设置一个值,另一个线程等待该值并输出通知。
题目要求:
-
使用
std::promise
设置一个整数值。 -
主线程通过
promise
设置值,另一个线程获取并输出该值。
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
using namespace std;
void task(promise<int>& prom) {
// 模拟一个耗时操作
this_thread::sleep_for(2s);
prom.set_value(100); // 设置任务完成的结果
}
int main() {
cout << "主线程开始..." << endl;
promise<int> prom;
future<int> fut = prom.get_future();
thread t(task, ref(prom)); // 启动一个线程,模拟任务执行
// 主线程等待任务完成并获取结果
cout << "主线程等待任务完成..." << endl;
cout << "Received value: " << fut.get() << endl; // 获取并打印结果
t.join(); // 等待子线程完成
cout << "主线程结束" << endl;
return 0;
}