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;
}
相關文章
相關標籤/搜索