C++11 - 管理工作线程

4

我对C++11中的线程编程还不熟悉,想知道如何使用标准库来管理工作线程,让它们执行某些任务并最终结束。我有一个线程池 vector<thread *> thread_pool,用于维护活跃线程列表。

假设我启动一个新线程,并将其添加到线程池中,使用 thread_pool.push_back(new thread(worker_task)),其中worker_task定义如下:

void worker_task()
{
    this_thread::sleep_for(chrono::milliseconds(1000));
    cout << "Hello, world!\n"
}

工作线程终止后,最可靠的方式是什么来从池中移除该线程?主线程需要持续运行,不能阻塞在join调用上。我比同步细节更关心代码的一般结构。

编辑:看起来我在代码中误用了池的概念。我的意思只是有一个正在运行的线程列表。


1
如果每个线程只执行一个任务,那么“线程池”的目的是什么? - nosid
2
在你考虑构建线程池架构之前,请阅读ftp://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html。 - Alexander Oh
那不是“pool”的意思... - Kerrek SB
@nosid 为了问题的简化,我展示的 worker_task 函数所创建的线程不会像那么短。而且,我需要能够随时显示所有线程正在处理的工作内容。实际上,thread_pool 不会包含线程对象列表,但会包含与每个线程相关的元数据。 - Chirag
@nosid OP从未写过那个,它是一个“线程池”,而不是“线程池”,OP还表示“执行一些任务然后死亡”,这是一个表明OP对“线程池”方法不感兴趣的陈述。 - user2485710
1个回答

3
您可以使用std::thread::detach来将“执行线程与线程对象分离,允许独立执行。一旦线程退出,任何已分配的资源都将被释放。” 如果每个线程应该使其状态可见,您可以将此功能移入线程函数中。
std::mutex mutex;
using strings = std::list<std::string>;
strings info;

strings::iterator insert(std::string value) {
    std::unique_lock<std::mutex> lock{mutex};
    return info.insert(info.end(), std::move(value));
}

auto erase(strings::iterator p) {
    std::unique_lock<std::mutex> lock{mutex};
    info.erase(p);
}

template <typename F>
void async(F f) {
    std::thread{[f] {
        auto p = insert("...");
        try {
            f();
        } catch (...) {
            erase(p);
            throw;
        }
        erase(p);
    }}.detach();
}

谢谢!我不知道detach函数,所以我会研究一下。但是关于你的代码,我有一个问题,为什么erase在catch里面?f完成时是否预期抛出异常? - Chirag
1
@Chirag:无论函数如何终止,都应该调用erase。然而,我错过了成功终止的情况。最好使用RAII代替。 - nosid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接