Bootstrap

c++11 thread基本使用记录

1.thread参数使用类

绑定类方法,直接使用std::thread(&CThread::run,&thread);

例子:

CThread thread;
std::thread th = std::thread(&CThread::run,&thread);

测试:

#include <iostream>
#include <thread>

using namespace std;

class CThread
{
public:
    CThread()
    {
        cout<<__FUNCTION__<<endl;
    }
    ~CThread()
    {
        cout<<__FUNCTION__<<endl;
    }
    void run(int n)
    {
        cout<<__FUNCTION__<<n<<endl;
    }
};

int main()
{
    CThread thread;
    std::thread th = std::thread(&CThread::run,&thread,10086);
    th.join();
    return 0;
}

输出结果:一次构造和析构,一次run调用

CThread
run10086
~CThread

注意 线程应该要指明join或者detach,否则程序会异常终止

测试

int main()
{
    CThread thread;
    std::thread th = std::thread(&CThread::run,&thread,10086);
   // th.join();
    return 0;
}

结果

CThread
run10086
terminate called without an active exception

解决办法

可以参考RAII封装,如下面第六条

2.使用普通方法

void fun_thread(int m)
{
     cout<<__FUNCTION__<<" "<<m<<endl;
}

int main()
{
    std::thread(fun_thread,100).join();
    return 0;
}

3. thread使用Lambda表达式

int main()
{
    std::thread([]{ cout<<"Lambda"<<endl;}).join();
    return 0;
}

4. 可以使用仿函数

class CThread
{
public:
    CThread()
    {
        cout<<__FUNCTION__<<" "<<this<<" "<<endl;
    }
    CThread(const CThread&)
    {
        cout<<__FUNCTION__<<" copy "<<this<<" "<<std::this_thread::get_id()<<endl;
    }
    ~CThread()
    {
        cout<<__FUNCTION__<<this<<" "<<std::this_thread::get_id()<<endl;
    }
    //仿函数
    void operator()() const
    {
       cout<<__FUNCTION__<<this<<" "<<std::this_thread::get_id()<<endl;
    }
};

int main()
{
    CThread thread;
    std::thread{thread}.join();
    return 0;
}

输出,有三次析构,即创建和到子线程都有拷贝

CThread 0x64febb 
CThread copy 0x64fe8b 1
CThread copy 0xe618ac 1
~CThread0x64fe8b 1
operator()0xe618ac 2
~CThread0xe618ac 2
~CThread0x64febb 1

5. 作为参数

可以作为参数传递

void threadCall(std::thread th)
{
    if(th.joinable()){
        th.join();
    }
}

int main()
{
    std::thread th =std::thread([]{ cout<<"Lambda"<<endl;});
    threadCall(std::move(th));
    return 0;
}

注意std::thread只能使用std::move,move前要确认是否当前可以赋值

int main()
{
    std::thread th =std::thread([]{ cout<<"Lambda1"<<endl;});
    std::thread th1 = std::move(th);
    th = std::thread([]{ cout<<"Lambda2"<<endl;});
     //th = std::move(th1);  //th已经再次创建(Lambda2),不能再赋值其他,会异常终止,即move后原先无法管理
    th1.join();
    th.join();
    return 0;
}

作为返回值

void createfun()
{
    cout<<__FUNCTION__<<" "<<endl;
}

std::thread createThread()
{
    return std::thread(createfun);
}

int main()
{
    createThread().join();
    return 0;
}

6.结合std::move未join异常处理

在一些临时创建线程,有时线程退出没有处理会程序退出,可以封装个类处理

class ScopedThread
{
public:
    explicit ScopedThread(std::thread t):m_thread{std::move(t)}
    {
        if(!m_thread.joinable()){
            throw std::logic_error("No thread");
        }
    }
    ~ScopedThread()
    {
        m_thread.join();
    }
    ScopedThread(const ScopedThread& )=delete;
    ScopedThread& operator=(const ScopedThread& )=delete;
private:
    std::thread m_thread;
};

int main()
{
    std::thread th{[]{std::this_thread::sleep_for(std::chrono::seconds(10));cout<<__FUNCTION__<<" "<<std::this_thread::get_id()<<endl;}};
    ScopedThread sth{std::move(th)};
    return 0;
}

查看可以运行线程数

std::thread::hardware_concurrency()

查看程序id

std::this_thread::get_id()

id可以比较

if(std::this_thread::get_id()==workid){...}
;