2016-01-21 97 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));