如何在 C++ 14 的类中启动线程?
Posted
技术标签:
【中文标题】如何在 C++ 14 的类中启动线程?【英文标题】:How to initiate a thread in a class in C++ 14? 【发布时间】:2019-12-20 15:28:42 【问题描述】:class ThreadOne
public:
ThreadOne();
void RealThread();
void EnqueueJob(s_info job);
std::queue<s_info> q_jobs;
private:
H5::H5File* targetFile = new H5::H5File("file.h5", H5F_ACC_TRUNC);
std::condition_variable cv_condition;
std::mutex m_job_q_;
;
ThreadOne::ThreadOne()
void ThreadOne::RealThread()
while (true)
std::unique_lock<std::mutex> lock(m_job_q_);
cv_condition.wait(lock, [this]() return !this->q_jobs.empty(); );
s_info info = std::move(q_jobs.front());
q_jobs.pop();
lock.unlock();
//* DO THE JOB *//
void ThreadOne::EnqueueJob(s_info job)
std::lock_guard<std::mutex> lock(m_job_q_);
q_jobs.push(std::move(job));
cv_condition.notify_one();
ThreadOne *tWrite = new ThreadOne();
我想创建一个线程并将一个数组指针及其名称作为结构(s_info)发送给它,然后让线程将其写入文件。我认为这比在需要写作的时候创建一个线程要好。
我可以创建一个线程池并为其分配作业,但在我的情况下不允许同时写入同一个文件,我认为只创建一个线程就足够了,程序仍然会执行 CPU 密集型作业写作工作正在进行中。
总而言之,这个类(希望)获取数组指针及其数据集名称,将它们放入q_jobs
和RealThread
将数组写入文件。
我提到了一个 C++ 线程池程序,该程序像这样启动线程:
std::vector<std::thread> vec_worker_threads;
vector_worker_threads.reserve(num_threads_);
vector_worker_threads.emplace_back([this]() this->RealThread(); );
我是 C++ 新手,我了解上面的代码的作用,但我不知道如何在没有向量的情况下在我的班级中启动 RealThread
。我怎样才能创建一个类的实例,其中包含一个已经准备好的线程(RealThread)?
【问题讨论】:
我不确定我是否完全掌握了困难的本质。如果你需要一个单线程,那么只需要一个std::thread
类型的变量。如果需要,该变量可以是某个类的成员;例如甚至可以成为ThreadOne
的成员。
@Igor Tandetnik 谢谢你的评论。你能举个例子吗?我记得读过你不能像在 main() 中使用函数那样只在类的实例中创建线程。
@maynull "我记得读过你不能像使用 main() 中的函数那样在类的实例中创建线程" 为什么?你是从哪里“记住”这个的?
class ThreadOne std::thread thread_; void StartThread() thread_ = std::thread([this] RealThread(); ); ;
类似的东西。
@IgorTandetnik 但是,不要忘记在析构函数中join
线程。
【参考方案1】:
据我所知,正如在 cmets 中已经讨论的那样,您只需要 ThreadOne
的 std::thread
成员:
class ThreadOne
std::thread thread;
public:
~ThreadOne();
//...
;
//...
ThreadOne::ThreadOne()
thread = std::threadRealThread, this;
ThreadOne::~ThreadOne()
// (potentially) notify thread to finish first
if(thread.joinable())
thread.join();
//...
ThreadOne tWrite;
请注意,我没有在构造函数的member-initializer-list中启动线程,以避免线程访问其他尚未初始化的成员。 (std::thread
的默认构造函数不会启动任何线程。)
我还写了一个析构函数,它将等待线程完成并加入它。在销毁附加到它的std::thread
对象之前,您必须始终加入线程,否则您的程序将调用std::terminate
并中止。
最后,我将tWrite
从一个指针直接替换为一个类类型。您可能没有理由在那里使用动态分配,即使您需要它,您也应该使用
auto tWrite = std::make_unique<ThreadOne>();
或等效的,这样您就不会依赖手动delete
将指针指向正确的位置。
另请注意,您当前的 RealThread
函数似乎永远不会完成。它必须在某个时候返回,可能是在收到主线程的通知之后,否则thread.join()
将永远等待。
【讨论】:
感谢您的详细解释和示例代码!以上是关于如何在 C++ 14 的类中启动线程?的主要内容,如果未能解决你的问题,请参考以下文章