c++ 11 多线程处理(1)

几种线程的方式

##建立线程ios

经过函数指针来建立一个线程

#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()c++

若是std::thread 对象没有任何关联的线程,get_id会返回一个默认的构造的std::thread::id对象 std::thread::id是一个对象,能够比较和输出 示例代码app

#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()函数ide

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()函数this

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的标准了。code

#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;
}
相关文章
相关标签/搜索