2012-05-19 38 views
13

我想学习如何用新的C++标准库创建多个线程并将它们的句柄存储到一个数组中。
如何启动线程?
我看到的例子用构造函数启动线程,但如果我使用数组,我无法调用构造函数。如何在C++ 11中创建线程对象数组?

#include <iostream> 
#include <thread> 

void exec(int n){ 
    std::cout << "thread " << n << std::endl; 
} 

int main(int argc, char* argv[]){ 

    std::thread myThreads[4]; 

    for (int i=0; i<4; i++){ 
     //myThreads[i].start(exec, i); //?? create, start, run 
     //new (&myThreads[i]) std::thread(exec, i); //I tried it and it seems to work, but it looks like a bad design or an anti-pattern. 
    } 
    for (int i=0; i<4; i++){ 
     myThreads[i].join(); 
    } 

} 

回答

35

没什么特别;只是使用任务。在你的循环内,写入

myThreads[i] = std::thread(exec, i); 

它应该工作。

+0

但它会创建一个临时对象,调用构造函数,执行赋值,然后调用析构函数。国家可能不一致。我试过了,它正在工作,但我不知道它是否会工作。 – Squall

+13

它使用移动语义。没有什么会不一致,它通过设计起作用。新执行线程的所有权将从临时数据库传递到数组元素,使临时数据与默认构造的线程对象处于相同状态,即不引用任何执行线程,因此可以安全销毁它。 –

-4

用C++ 0x/C++ 11,尝试使用矢量而不是线程数组;是这样的:

vector<thread> mythreads; 
int i = 0; 
for (i = 0; i < 8; i++) 
{ 
    mythreads.push_back(dostuff, withstuff); 
} 
auto originalthread = mythreads.begin(); 
//Do other stuff here. 
while (originalthread != mythreads.end()) 
{ 
    originalthread->join(); 
    originalthread++; 
} 

编辑:如果你真的想自己处理内存的分配和使用指针数组(即向量只是是不是你的东西),那么我可以不推荐Valgrind的高度不够。它有内存分配检查器和线程检查器等等,对于这种事情是无价的。在任何情况下,这里的使用手动分配的线程的阵列的示例性程序,并且它本身后清理(无内存泄漏):所需

#include <iostream> 
#include <thread> 
#include <mutex> 
#include <cstdlib> 

// globals are bad, ok? 
std::mutex mymutex; 


int pfunc() 
{ 
    int * i = new int; 
    *i = std::rand() % 10 + 1; 

    // cout is a stream and threads will jumble together as they actually can 
    // all output at the same time. So we'll just lock to access a shared 
    // resource. 
    std::thread::id * myid = new std::thread::id; 
    *myid = std::this_thread::get_id(); 
    mymutex.lock(); 
    std::cout << "Hi.\n"; 
    std::cout << "I'm threadID " << *myid << std::endl; 
    std::cout << "i is " << *i << ".\n"; 
    std::cout << "Bye now.\n"; 
    mymutex.unlock(); 

    // Now we'll sleep in the thread, then return. 
    sleep(*i); 
    // clean up after ourselves. 
    delete i; 
    delete myid; 
    return(0); 
} 


int main() 
{ 

    std::thread * threadpointer = new std::thread[4]; 
    // This seed will give us 5, 6, 4, and 8 second sleeps... 
    std::srand(11); 
    for (int i = 0; i < 4; i++) 
    { 
     threadpointer[i] = std::thread(pfunc); 
    } 
    for (int i = 0; i < 4; i++) 
     // Join will block our main thread, and so the program won't exit until 
     // everyone comes home. 
    { 
     threadpointer[i].join(); 
    } 
    delete [] threadpointer; 
} 
+1

@Nevin(因为我不能评论任何人的答案)您是否尝试过通过valgrind --tool = helgrind运行您的解决方案?我在GCC 4.5.2上,从输出中看到它看起来像你所显示的线程实际上是通过C++ 11线程进入未定义的行为区域。 – Kionmaru

+6

没有必要这么用'new' /'delete'。 –

+1

Kionmaru,在使用helgrind和std :: thread之前,请参阅http://stackoverflow.com/a/10624266/981959。 –