NIUCLOUD是一款SaaS管理后台框架多应用插件+云编译。上千名开发者、服务商正在积极拥抱开发者生态。欢迎开发者们免费入驻。一起助力发展! 广告
# 线程C++封装 ### 头文件定义 ~~~ #ifndef _LEO_THREAD_H_ #define _LEO_THREAD_H_ ​ #include "Noncopyable.h" #include <functional> ​ namespace leo { ​ class Thread : public Noncopyable { public: typedef std::function<void ()> Func; ​ Thread(Func cb, const std::string& name = ""); ​ ~Thread(); ​ void start(); ​ void join(); ​ bool isStarted() const { return started_; } ​ const std::string& getName() const { return name_; } ​ static pid_t CurrentThreadTid(); ​ private: static void* threadFuncInternal(void* arg); ​ bool started_;       // 开始 bool joined_;        // join标志 pthread_t tid_;      // 线程id std::string name_;   // 线程名称 Func cb_;            // 回调函数 }; ​ } ​ #endif ~~~ 线程join理解 命名来源于posix标准。子线程join到主线程(启动程序的线程,比如c语言执行main函数的线程)。你的问题可能在于没有理解join,阻塞线程仅仅是一个表现,而非目的。其目的是等待当前线程执行完毕后,”计算单元”与主线程汇合。即主线程与子线程汇合之意。 main是主线程,在main中创建了thread线程,在main中调用了thread.join(),那么等thread结束后再执行main代码。 在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。 ### cpp实现 ~~~ #include "Log.h" ​ #include <assert.h> #include <atomic> #include <sys/syscall.h> #include <string.h> #include <Thread.h> #include <unistd.h> ​ namespace leo { ​ std::atomic<int> threadCount(0); static __thread pid_t t_tid = 0; ​ pid_t Thread::CurrentThreadTid() { if (t_tid == 0) t_tid = ::syscall(SYS_gettid); return t_tid; } ​ Thread::Thread(Func cb, const std::string& name) : started_(false),  joined_(false),  cb_(std::move(cb)) { if (name.empty()) { int num = threadCount.fetch_add(1); name_ = "Thread-" + std::to_string(num); } else { name_ = name; } } ​ Thread::~Thread() { if (started_ && !joined_) { pthread_detach(tid_); } } ​ void Thread::start() { assert(!started_); started_ = true; if (int error = pthread_create(&tid_, nullptr, Thread::threadFuncInternal, this)) { started_ = false; LOG_FATAL << "pthread_create failed, " << strerror(error); } } ​ void Thread::join() { assert(started_); assert(!joined_); joined_ = true; if (int error = pthread_join(tid_, nullptr)) { joined_ = false; LOG_FATAL << "pthread_join failed, " << strerror(error); } } ​ void* Thread::threadFuncInternal(void* arg) { Thread* thread = static_cast<Thread*>(arg); Func cb; cb.swap(thread->cb_); cb(); return 0; } ​ } ~~~ ### 测试 ~~~ #include "Thread.h" #include "Log.h" #include <sys/syscall.h> #include <unistd.h> ​ using namespace std; using namespace leo; ​ void func() { LOG_DEBUG << "thread func: " << Thread::CurrentThreadTid(); while (1) { LOG_DEBUG << "poll thread id=" << Thread::CurrentThreadTid(); sleep(1); } } ​ int main() { Singleton<Logger>::getInstance()->addAppender("console", LogAppender::ptr(new ConsoleAppender())); ​ Thread t1(func, "leo_thread"); Thread t2(func); ​ LOG_DEBUG << "t1 name=" << t1.getName(); LOG_DEBUG << "t2 name=" << t2.getName(); LOG_DEBUG << "main thread: " << Thread::CurrentThreadTid(); LOG_DEBUG << "thread start ..."; ​ t1.start(); t2.start(); ​ t1.join(); t2.join(); return 0; } ~~~ ![1606141348371](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/1606141348371.png?lastModify=1606141361)