當(dāng)一些異步的任務(wù)的時候衬廷,使用C++來創(chuàng)建線程來做任務(wù)的時候巷疼,
可以引用std::thread這個庫
使用方法如下,創(chuàng)建一個線程珊膜,里面通過std::bind來綁定方法任務(wù)容握。
std::thread thread = std::thread(std::bind(&類名::方法名,this 參數(shù));
這只是初始化線程
thread.join()
等著線程執(zhí)行完成之后,主線程才能執(zhí)行下去,此時主線程會立刻釋放子線程占用的資源
thread.detach()
主線程不需要等待子線程執(zhí)行完成车柠,主線程和子線程分離
這是簡單的線程調(diào)用剔氏,而C++中并沒封裝好線程池給我們使用。這里網(wǎng)上找了一個例子竹祷,可以簡單看看注釋谈跛。
#include <functional>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <queue>
#include <condition_variable>
#include <future>
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
namespace std { //聲明std的作用域
#define MAX_THREAD_NUM = 256
class MagicThreadPool {
public:
//內(nèi)聯(lián)函數(shù),
inline MagicThreadPool(unsigned short size = 4) : stoped{false} {
//線程池大小
idlThrNum = size < 1 ? 1 : size;
for (size = 0; size < idlThrNum; ++size) { //初始化線程數(shù)量
// 只有一次構(gòu)造函數(shù)塑陵,不調(diào)用拷貝構(gòu)造函數(shù)感憾,速度最快
pool.emplace_back(
[this] { // 工作線程函數(shù)
while (!this->stoped) {
//聲明任務(wù)
std::function<void()> task;
{ // 獲取一個待執(zhí)行的 task
std::unique_lock<std::mutex> lock{this->m_lock};// unique_lock 相比 lock_guard 的好處是:可以隨時 unlock() 和 lock()
this->cv_task.wait(lock,
[this] {
return this->stoped.load() ||
!this->tasks.empty();
}
); // wait 直到有 task
if (this->stoped && this->tasks.empty())
return false;
task = std::move(this->tasks.front()); // 取一個 task
this->tasks.pop();
}
idlThrNum--;
//運行任務(wù)
task();
idlThrNum++;
}
}
);
}
}
//析構(gòu)函數(shù)
inline ~MagicThreadPool() {
//停止全部任務(wù)
stoped.store(true);
cv_task.notify_all(); // 喚醒所有線程執(zhí)行
for (std::thread &thread : pool) {
//thread.detach(); // 讓線程“自生自滅”
if (thread.joinable())
thread.join(); // 等待任務(wù)結(jié)束, 前提:線程一定會執(zhí)行完
}
}
//模板令花,需要聲明類的類型阻桅,自動匹配返回值
template<class F, class... Args>
auto commit(F &&f, Args &&... args) -> std::future<decltype(f(args...))> {
//直接停止任務(wù)
if (stoped.load()) // stop == true ??
throw std::runtime_error("commit on ThreadPool is stopped.");
using RetType = decltype(f(
args...)); // typename std::result_of<F(Args...)>::type, 函數(shù) f 的返回值類型
//自動返回值
auto task = std::make_shared<std::packaged_task<RetType()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
); // wtf !
std::future<RetType> future = task->get_future();
{ // 添加任務(wù)到隊列
std::lock_guard<std::mutex> lock{
m_lock};//對當(dāng)前塊的語句加鎖 lock_guard 是 mutex 的 stack 封裝類,構(gòu)造的時候 lock()兼都,析構(gòu)的時候 unlock()
tasks.emplace( //放入任務(wù)到任務(wù)池
[task]() { // push(Task{...})
(*task)();
}
);
}
cv_task.notify_one(); // 喚醒一個線程執(zhí)行
return future;
};
//空閑線程數(shù)量
int idlCount() { return idlThrNum; }
private:
using Task = std::function<void()>;
//線程池
std::vector<std::thread> pool;
//任務(wù)隊列
std::queue<Task> tasks;
//同步鎖
std::mutex m_lock;
std::condition_variable cv_task;
std::atomic<bool> stoped;
std::atomic<int> idlThrNum;
};
}
#endif
使用方式嫂沉,這類方法需要聲明為static調(diào)用的方法
pool->commit(類名::方法名,參數(shù));
這里注意一定不要這里是一個MagicThreadPool.h文件扮碧,千萬別想因為代碼好看分成兩個h和cpp來寫趟章。
因為cpp將會編譯好的代碼,是無法更改的,無法進行模板在線程調(diào)用方法中的參數(shù)推導(dǎo)尤揣。會無法編譯通過搔啊。
如果想看具體的流程可以看我MagicCamera3的代碼
地址是MagicCamera3 https://github.com/cangwang/MagicCamera3,歡迎大家下載和點贊柬祠,如果有問題北戏,也可以進我的組件化群1和群2,來討論問題漫蛔。