并发与多线程(2)

一、使用函数对线程的创建、启动、结束

     (1)包含头文件    

 #include <thread>

       (2)  写初始函数(根据需求自己定义)

 void MyPrintf()           
 {
    cout<<"我创建的线程开始执行了"<<endl;
    ...
    cout<<"我创建的线程执行结束了"<<endl;
 }

   (3)定义对象     

            3.1 thread是标准库中的一个类 

            3.2 join()加入汇合,阻塞主线程执行

            3.3 良好的书写规范:主线程必须等待子线程执行完毕后,才能关闭退出

int mian()
{
    // thread是标准库中的一个类 ,MyPrintf是实参,是可调用对象
    //(1)创建了线程,线程执行起点(入口)MyPrintf  (2)开始执行线程MyPrintf方法  
    thread myObj(MyPrintf);                      

    //join()作用:主线程阻塞到这里,等待子线程MyPrintf执行完,当子线程执行完毕,和主线程会合,然后继续向下继续执行
    myObj.join()

    return 0;
}

  (4)detach()  

           4.1 作用:分离主线程和子线程的依赖关系,主线程不用等待子线程汇合,也可以退出;

           4.2 一旦detach后,与主线程关联的thread对象就会失去关联,子线程就会驻留在后台继续执行,由后台运行时库进行线程资源的清理工作;

           4.3 使用detach(),就不能再用join();

int mian()
{
    thread myObj(MyPrintf);                      

    myObj.detach();

    return 0;
}

(5)joinable()

         作用:判断是否可以使用join()或者detach(),返回值是bool类型

int mian()
{
    thread myObj(MyPrintf);                   

    if(myObj.joinable())
    {
        //可以执行join汇合,具体实现根据需求自己定义
        myObj.join()   
        ...
    }
    else
    {
        //可以执行detach分离
        myObj.detach()   
        ...
    }

    return 0;
}

二、其他创建线程的方法

      (1)使用类:

class TA
{
public:
    void operator()()                //不带参数
    { 
        cout<<"我的线程执行开始了"<<endl;
        ......
        cout<<"我的线程执行结束了"<<endl;
    }
};

int mian()
{
    TA a;
    thread mythread(a);            //通过类对象调用,执行线程
    a.join();

    return 0;
}
class TA
{
public:
    int &m_i;                                    //成员变量为引用时,不能用detach(),如果是int整形普通变量则可以,考虑引用内存回收的问题

    TA(int &i):m_i(i)
    {}

    void operator()()                            //带参数
    { 
        cout << "我的线程执行开始了" << endl;
        cout << "m_i的值为:"<< m_i << endl;
        cout << "我的线程执行结束了" << endl;
    }
};

int mian()
{
    int num = 9;
    TA ta(num);
    thread mythread(ta);                         //通过类对象调用,执行线程
    ta.join();

    //注意:成员变量不是引用或者指针,一旦调用了detach(),主线程执行完毕后,ta会被销毁,ta对象就不存在了;但是对象ta会被复制一份到线程中依旧存在,继续执行;
    // ta.detach();

    return 0;
}
class TA
{
public:
    int m_i;                                    //成员变量为引用时,不能用detach(),如果是int整形普通变量则可以,考虑引用内存回收的问题

    TA(int i):m_i(i)
    {
        cout << "构造函数被执行" << endl;
    }
    TA(const TA &ta):m_i(ta.m_i)
    {
        cout << "拷贝构造函数被执行" << endl;
    }

    ~TA()
    {
        cout<<"析构函数被执行"<<endl;
    }

    void operator()()                            //带参数
    { 
        cout << "我的线程执行开始了" << endl;
        cout << "m_i的值为:"<< m_i << endl;
        cout << "我的线程执行结束了" << endl;
    }
};

int mian()
{
    int num = 9;
    TA ta(num);
    thread mythread(ta);                         //通过类对象调用,执行线程

    //注意:成员变量不是引用或者指针,一旦调用了detach(),主线程执行完毕后,ta会被销毁,ta对象就不存在了;但是对象ta会被复制一份到线程中依旧存在,继续执行;
    mythread.detach();
                        //析构函数会被执行两次,第一次是主线程结束的析构,第二次是复制后的析构;
    return 0;
}

    (2)使用Lambda表达式

int mian()
{
    auto myLamthread[]
    {
        cout << "我的线程执行开始了" << endl;
        ....
        cout << "我的线程执行结束了" << endl;

    }

    thread mythread(myLamthread);                         //通过lambda表达式调用,执行线程

    mythread.join();
                        
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41734758/article/details/109101389