文档章节

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

罗布V
 罗布V
发布于 2016/07/07 23:28
字数 1484
阅读 135
收藏 1

几种线程的方式

##创建线程

通过函数指针来创建一个线程

#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;
}

© 著作权归作者所有

罗布V
粉丝 13
博文 60
码字总数 47114
作品 0
温州
程序员
私信 提问
Linux平台下基于TCP/IP协议的C++网络编程初步

Linux平台下基于TCP/IP协议的C++网络编程初步 实验平台:Ubuntu(Linux) 开发工具:Eclipse+CDT 作者:@郑海波 http://blog.csdn.net/nuptboyzhb/ 特点: 1.基于Linux平台的网络编程,最重要的...

长平狐
2012/10/08
1K
1
C++雾中风景12:聊聊C++中的Mutex,以及拯救生产力的Boost

笔者近期在工作之中编程实现一个Cache结构的封装,需要使用到C++之中的互斥量Mutex,于是花了一些时间进行了调研。(结果对C++标准库很是绝望....)最终还是通过利用了Boost库的shared_mute...

LeeHappen
2018/10/06
0
0
C++ 类库资源

原文:C++ 类库资源 作者:Breaker C/C++ 开发库 | C/C++ Development Library 这里收集一些著名的 C/C++ 开发库、SDK、类库、可复用类与结构代码 等信息,列举它们的介绍、参考和网站链接,...

晨曦之光
2012/05/23
1K
0
[Android] 图片JNI(C++\Java)高斯模糊 多线程

======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处:http://blog.csdn.......

Qiujuer
2014/12/06
0
8
[Android] 图片JNI(C++\Java)高斯模糊 多线程

======================================================== 作者:qiujuer 博客:http://my.oschina.net/u/1377710/blog 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处:h......

Qiujuer
2014/12/06
749
1

没有更多内容

加载失败,请刷新页面

加载更多

ngrok 外网映射工具

ngrok介绍 许多刚学java web的同学(包括我自己)肯定都非常好奇,如何在外网上访问自己做的项目,跟我们本地访问tomcat有什么区别? 今天就向大家介绍一个非常强大的外网映射工具:ngrok.ngrok可以...

edison_kwok
53分钟前
2
0
Spark Streaming的优化之路——从Receiver到Direct模式

          作者:个推数据研发工程师 学长 1 业务背景 随着大数据的快速发展,业务场景越来越复杂,离线式的批处理框架MapReduce已经不能满足业务,大量的场景需要实时的数据处理结果来...

个推
今天
4
0
壮丽70年·奋斗新时代|蒸妙集团熏蒸中会阴熏蒸的神奇好处

聚结相合之处为会。会阴居两阴间,为督、任、冲三脉的起点,三脉背出两阴之间,会聚阴部,因名会阴。会阴,经穴名。出《针灸甲乙经》。会阴别名屏翳、下极、金门。属任脉。在会阴部,男性当阴...

公益传承
今天
2
0
pentaho-kettle-8.2.0.0-R源码开发环境搭建

1.从Kettle官网下载源码,本文使用的是pentaho-kettle-8.2.0.0-R 下载地址:https://codeload.github.com/pentaho/pentaho-kettle/zip/8.2.0.0-R 2.打开eclipse,选择一个新的工作空间,然后设...

gq_2010
今天
1
0
lua web快速开发指南(7) - 高效的接口调用 - httpc库

httpc库基于cf框架都内部实现的socket编写的http client库. httpc库内置SSL支持, 在不使用代理的情况下就可以请求第三方接口. httpc支持header、args、body、timeout请求设置, 完美支持各种h...

水果糖的小铺子
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部