2016-01-21 66 views
1

让我们假设我们有两个功能的情况:运行C++线程()

void foo1() { 
    while (true) { 
     std::cout << "foo1" << std::endl; 
     std::this_thread::sleep_for (std::chrono::milliseconds {100}); 
    } 
} 

void foo2() { 
    while (true) { 
     std::cout << "foo2" << std::endl; 
     std::this_thread::sleep_for (std::chrono::milliseconds {100}); 
    } 
} 

,我要开始他们在不同的线程,但它们是否开始是依赖于某些条件,所以例如他们的执行就像下面:

bool c1 {true}; 
bool c2 {true}; 

if (c1) { 
    std::thread th1 {&foo1}; 
    th1.join(); 
} 

if (c2) { 
    std::thread th2 {&foo2}; 
    th2.join(); 
} 

我这里在这种情况下,只知道foo1()将被调用和foo2()从来没有。

我首先想到的是使用unique_ptr这样的:

bool c1 {false}; 
bool c2 {false}; 

std::unique_ptr<std::thread> pth1 {}; 
std::unique_ptr<std::thread> pth2 {}; 

if (c1) { 
    pth1 = std::unique_ptr<std::thread> {new std::thread {&foo1}}; 
} 

if (c2) { 
    pth2 = std::unique_ptr<std::thread> {new std::thread {&foo2}}; 
} 

if (pth1) { 
    pth1->join(); 
} 

if (pth2) { 
    pth2->join(); 
} 

我的第二个想法是改变一下设计始终运行的线程,但如果条件为假,退出功能,所以来看看下面的代码:

void foo1 (bool c) { 
    if (c) { 
     while (true) { 
      std::cout << "foo1" << std::endl; 
      std::this_thread::sleep_for (std::chrono::milliseconds {100}); 
     } 
    } 
} 

void foo2 (bool c) { 
    if (c) { 
     while (true) { 
      std::cout << "foo2" << std::endl; 
      std::this_thread::sleep_for (std::chrono::milliseconds {100}); 
     } 
    } 
} 

bool c1 {true}; 
bool c2 {true}; 

std::thread th1 {&foo1, c1}; 
std::thread th2 {&foo2, c2}; 

th1.join(); 
th2.join(); 

我知道问哪个更好并不总是很好的问题,但你可以建议我好了(也许比呈现更好)解决方案来处理的情况时,至少有两个线程开始来自不同的sc开放和所有他们必须加入?

+1

为什么不把线程保存在一个容器(如'vector')中,然后用循环加入容器中的所有线程? –

回答

4

A std::thread对象不必表示线程。我认为,最简单的就是:

std::thread th1, th2; 
    if (c1) 
     th1 = std::thread{&foo1}; 
    if (c2) 
     th2 = std::thread{&foo2}; 

    if (th1.joinable()) 
     th1.join(); 
    if (th2.joinable()) 
     th2.join(); 

甚至:

std::thread maybe_start(void(*f)(), bool c) 
{ 
    if (c) 
     return std::thread{f}; 
    else 
     return {} 
} 
void maybe_wait(std::thread& thr) 
{ 
    if (thr.joinable()) 
     thr.join(); 
} 

.... 
    std::thread thr1 = maybe_start(&foo1, c1); 
    std::thread thr2 = maybe_start(&foo2, c2); 

    maybe_wait(thr1); 
    maybe_wait(thr2); 
0

你需要一个像线程池的一些事情。我写这个例子来说明想法:

#ifndef DUMMYTHREADPOOL_H_ 
#define DUMMYTHREADPOOL_H_ 

#include <thread> 

class dummy_thread_pool { 
private: 
    std::vector<std::thread> tp; 

    dummy_thread_pool(const dummy_thread_pool&){} 

public: 
    dummy_thread_pool(){} 

    dummy_thread_pool(size_t n) 
    { 
     tp.reserve(n); 
    } 

    ~dummy_thread_pool() 
    { 
     tp.clear(); 
    } 

    void do_join(std::thread& t) 
    { 
     t.join(); 
    } 

    void join_all() { 
     std::for_each(tp.begin(), tp.end(), std::bind(&dummy_thread_pool::do_join, this, std::placeholders::_1)); 
    } 

    void wait_for_all() 
    { 
     std::thread t(&dummy_thread_pool::join_all, this); 

     t.join(); 
    } 

    void add_thread(std::thread t) 
    { 
     tp.push_back(std::move(t)); 
    } 
}; 



#endif /* DUMMYTHREADPOOL_H_ */ 

您的代码可能看起来像这样:

bool c1 {true}; 
bool c2 {true}; 
dummy_thread_pool dtp; 

if (c1) { 
    std::thread th1 {&foo1}; 
    dtp.add_thread(std::move(th1)); 
} 

if (c2) { 
    std::thread th2 {&foo2}; 
    dtp.add_thread(std::move(th2)); 
} 

dtp.wait_for_all(); 

而且你的情况可能是有用的std::futurestd::async而不是std::thread。你

也可以使用boost::thread_group

boost::thread_group tg; 
tg.create_thread(/*your thread*/); 
tg.join_all(); 
0

你的第二个解决方案是相当不错的。但我们必须不要忘记拨打join方法。为了简化你可以使用RAII这样:

class thread_guard 
{ 
    std::thread thread_; 

public: 
    explicit thread_guard(std::thread thread) 
     thread_{ std::move(thread) } 
    { 
     if (!thread.joinable()) { 
      throw std::logic_error("No joinable thread!"); 
     } 
    } 

    ~thread_guard() { 
     thread_.join(); 
    } 

    thread_guard(const thread_guard&) = delete; 
    thread_guard & operator=(const thread_guard&) = delete; 
}; 

void f() { 
    thread_guard thread1(std::thread(&foo1, c1)); 
} 

您也可以使用螺纹调查与thread_guard,但在这种情况下,用少量的线程它更复杂的

,或者它可以非常做到这一点简单的方法:

std::vector<std::thread> threads; 
//add threads in vector 
std::for_each(threads.begin(),threads.end(), 
    std::mem_fn(&std::thread::join));