几种线程的方式
##创建线程
通过函数指针来创建一个线程
#include <iostream>
#include <thread>
void thread_function(){
for (int i = 0; i < 10000; i++) {
std::cout<<"thread function Executing"<<std::endl;
}
}
int main(int argc, char const* argv[])
{
std::thread threadobj(thread_function);
for (int i = 0; i < 10000; i++) {
std::cout<<"Display From MainTHread"<<std::endl;
}
threadobj.join();
std::cout<<"Exit of Main function"<<std::endl;
return 0;
}
使用函数对象创建一个线程
#include <iostream>
#include <thread>
class DisplayThread{
public:
void operator()(){
for (int i = 0; i < 10000; i++) {
std::cout<<"Display Thread executing"<<std::endl;
}
}
};
int main(int argc, char const* argv[])
{
std::thread threadobj((DisplayThread()));
for (int i = 0; i < 10000; i++) {
std::cout<<"Display from main thread"<<std::endl;
}
std::cout<<"Waiting for thread to complete"<<std::endl;
threadobj.join();
std::cout<<"Exiting from main thread"<<std::endl;
return 0;
}
使用 匿名函数来创建线程
#include <iostream>
#include <thread>
int main(){
int x=9;
std::thread threadObj([]{
for (int i=0;i<10000;i++)
std::cout<<"Display thread executeing"<<std::endl;
});
for (int i = 0; i < 10000; i++) {
std::cout<<"Display from main thread"<<std::endl;
}
threadObj.join();
std::cout<<"Exiting from Main Thread"<<std::endl;
return 0;
}
不同线程之间的区别
第一个线程都会有一个ID 成员函数指定关联线程对象的ID std::thread::get_id() 给出当前函数的标识符 std::this_thread::get_id()
如果std::thread 对象没有任何关联的线程,get_id会返回一个默认的构造的std::thread::id对象 std::thread::id是一个对象,可以比较和输出 示例代码
#include <iostream>
#include <thread>
void thread_function(){
std::cout<<"Inside Thread :: ID="<<std::this_thread::get_id()<<std::endl;
}
int main(int argc, char const* argv[])
{
std::thread threadObj1(thread_function);
std::thread threadObj2(thread_function);
if(threadObj1.get_id()!=threadObj2.get_id())
std::cout<<"BOth threads have diferent IDs"<<std::endl;
std::cout<<"From Main thread :: id of thread 1="<<threadObj1.get_id()<<std::endl;
std::cout<<"From Main thread :: id of thread 2="<<threadObj2.get_id()<<std::endl;
return 0;
}
加入和分离线程
joining 线程 一旦线程开始启动之后,其他的线程可以等待这个新的线程完成。等到其他的线程调用 join()函数
std::thread th(funPtr); th.join() 我们来看一个示例 假设主线程已经启动了10个线程,直到所有的线程结束之后再退出。
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
class WorkerThread {
public:
void operator()(){
std::cout<<"Worker Thread "<<std::this_thread::get_id()<<" is Executing "<<std::endl;
}
};
int main(int argc, char const* argv[])
{
std::vector<std::thread> threadList;
for (int i = 0; i < 10; i++) {
threadList.push_back(std::thread(WorkerThread()));
}
std::cout<<"等待所有的工作线程完成"<<std::endl;
std::for_each(threadList.begin(),threadList.end(),std::mem_fn(&std::thread::join));
std::cout<<"退出主线程"<<std::endl;
return 0;
}
分离线程 分享之后的线程也称做后台进程。分离一个线程我们需要调用 std::detach()函数
std::thread th(funcPtr); th.detach();
一旦分享之后并不会再跟主线程关联 所以我们需要小心的使用detach()和join() 避免出现不可预知的问题
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
class WorkerThread {
public:
void operator()(){
std::cout<<"Worker Thread "<<std::this_thread::get_id()<<" is Executing "<<std::endl;
}
};
int main(int argc, char const* argv[])
{
std::thread threadObj((WorkerThread()));
if ( threadObj.joinable() )
{
std::cout<<"Detaching Thread "<<std::endl;
threadObj.detach();
}
if ( threadObj.joinable() )
{
std::cout<<"Detaching Thread "<<std::endl;
threadObj.detach();
}
std::thread threadObj2((WorkerThread()));
if ( threadObj2.joinable() )
{
std::cout<<"Detaching Thread "<<std::endl;
threadObj2.detach();
}
if ( threadObj2.joinable() )
{
std::cout<<"Detaching Thread "<<std::endl;
threadObj2.detach();
}
return 0;
}
#include <iostream>
#include <thread>
class ThreadRAII
{
std::thread & m_thread;
public:
ThreadRAII(std::thread & threadObj) : m_thread(threadObj)
{
}
~ThreadRAII()
{
// 判断线程是否可被分离
if(m_thread.joinable())
{
m_thread.detach();
}
}
};
void thread_function()
{
for(int i = 0; i < 10000; i++)
std::cout<<"thread_function Executing"<<std::endl;
}
int main()
{
std::thread threadObj(thread_function);
// 如果我们注释这行程序并会崩溃
ThreadRAII wrapperObj(threadObj);
return 0;
}
传递参数给线程
其中chrono原是boost的一个时间处理的库,现已成为c++ 11的标准了。
#include <iostream>
#include <thread>
void newThreadCallback(int *p){
std::cout<<"Inside Thread :"":p="<<p<<std::endl;
std::chrono::milliseconds dura(10000);
std::this_thread::sleep_for(dura);
*p=19;
}
void startNewThtread(){
int i=10;
std::cout<<"Inside Main Thread:"":i= "<<i<<std::endl;
std::thread t(newThreadCallback,&i);
t.detach();
std::cout<<"Inside Main Thread : "": i="<<i<<std::endl;
}
int main(int argc, char const* argv[])
{
startNewThtread();
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
return 0;
}
有的时候我们需要注意的是,当你将一个对象的指针传递给一个线程时,而这个对象可能在传递的线程之外被删除,那么该线程再次访问的时候会出现段错误。比如说下面的这段程序
#include <iostream>
#include <thread>
void newThreadCallback(int* p){
std::cout<<"inside Thread :"":p="<<p<<std::endl;
std::chrono::milliseconds dura(1000);
std::this_thread::sleep_for(dura);
*p=19;
}
void startNewThread(){
int *p=new int();
*p=10;
std::cout<<"Inside Main Thread:"":*p="<<*p<<std::endl;
std::thread t(newThreadCallback,p);
t.detach();
delete p;
p=NULL;
}
int main(int argc, char const* argv[])
{
startNewThread();
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
return 0;
}
给线程传递一个形参
有的时候我们需要在程序中将某一些对象添加到某一线程的堆栈当中,一旦在线程里面更新并可以同步到主线程当中。
#include <iostream>
#include <thread>
void threadCallback(int const & x){
int &y=const_cast<int &>(x);
y++;
std::cout<<"Inside Thread x="<<x<<std::endl;
}
int main(int argc, char const* argv[])
{
int x=9;
std::cout<<"In main thread :before thread start x ="<<x<<std::endl;
std::thread threadObj(threadCallback,x);
threadObj.join();
std::cout<<"In main thread : after thread joins x="<<x<<std::endl;
return 0;
}
输出 In main thread :before thread start x =9 Inside Thread x=10 In main thread : after thread joins x=9
上面的程序看似threadCallback接收一个形参,在传递给threadCallback的时候线程会复制一个临时的值,更改该值并不影响外面的变量
倘若我们需要实际在线程里面改变外部的值,需要通过std::ref()的方式来传递值。
#include <iostream>
#include <thread>
void threadCallback(int const & x){
int &y=const_cast<int &>(x);
y++;
std::cout<<"Inside thread x ="<<x<<std::endl;
}
int main(int argc, char const* argv[])
{
int x=9;
std::cout<<"in main thread:before thread start x="<<x<<std::endl;
std::thread threadObj(threadCallback,std::ref(x));
threadObj.join();
std::cout<<"In Main Thread :After thread joins x ="<<x<<std::endl;
return 0;
}
输出: in main thread:before thread start x=9 Inside thread x =10 In Main Thread :After thread joins x =10
实现一个线程类的功能
在创建的thread的时候其中第一项传递的是成员函数做为线程的回调函数,而第二项传递的是操作的对象。
#include <iostream>
#include <thread>
class DummyClass {
public:
DummyClass()
{}
DummyClass(const DummyClass & obj)
{}
void sampleMemberFunction(int x)
{
std::cout<<"Inside sampleMemberFunction "<<x<<std::endl;
}
};
int main() {
DummyClass dummyObj;
int x = 10;
std::thread threadObj(&DummyClass::sampleMemberFunction,&dummyObj, x);
threadObj.join();
return 0;
}