原文:https://www.cnblogs.com/wangkeqin/p/9351299.html

Thread线程框架

线程定义:
线程可以理解为一个特立独行的函数。其存在的意义,就是并行,避免了主线程的阻塞。

----------------------------thread与函数----------------------------------

线程启动

  C++线程的启动, 只需要#include <thread>即可。 线程对象的创建, 意味着线程的开始。

1)同步

#include <iostream>
#include <thread>
#include <unistd.h> using namespace std; void func()
{
cout<<"thread id:"<<this_thread::get_id()<<endl;
cout<<"do some work"<<endl;
sleep(3);
}
int main()
{
cout<<"maint thread id:"<<this_thread::get_id()<<endl;
thread t(func);
t.join();
return 0;
}

  t.join 和 t.detach 标志着, 线程对象和线程的关系。 t.join 表示, 线程与线程对象的同步关系。 而 t.detach 表示, 线程与线程对象的异步关系。 在线程生成后,必须指定join或者detach状态来。

  detach 后的线程,不能再 join,是否可以 join 可以通过 joinable 来判断。 

2)异步

#include <iostream>
#include <memory> using namespace std; void func()
{
cout<<"thread id:"<<this_thread::get_id()<<endl;
int i = 0;
while(i++<5)
{
cout<<"assist thread running times:"<<i<<endl;
sleep(1);
}
cout<<"----end assist thread work!------"<<endl;
} int main()
{
cout<<"maint thread id:"<<this_thread::get_id()<<endl;
thread t(func);
// t.join(); //!同步
t.detach(); //!异步 int i =0;
while(i++<10)
{
cout<<"main thread running times:"<<i<<endl;
sleep(1);
}
cout<<"-----main thread finished!-----"<<endl;
}

  在次线程detach的状态下,要保证主线程的上声明周期要比次线程声明周期长,否则此线线程将中断退出。

传参方式

  线程有自己独立的栈。可供享受全局的变量。在线程启动的时候可以传入启动的参数。

#include <iostream>
#include <thread>
using namespace std; void func(int n, string s)
{
for(int i=0;i <n ;i++)
{
cout<<s<<endl;
}
}
int main()
{
thread t(func,5,"china");
t.join();
return 0;
}

  除了传入参数,共享全局以外,还可以使用std::ref辅助传入本地变量的引用。thread认为不加std::ref包装的变量都是以拷贝的方式传入线程中去的。

#include <iostream>
#include <thread>
using namespace std; void func(int &n, string &s)
{
for(int i=0;i <n ;i++)
{
cout<<s<<endl;
}
n = 10;
s = "america";
} int main()
{
int n = 5;
string s = "china";
// thread t(func,n, s); //!编译不过,thread无法区分传入的参数
thread t(func,ref(n), ref(s)); //!正确的传引用的姿势,应该采用std::ref来对变量包装
t.join();
return 0;

 

----------------------------thread与类成员函数-----------------------------------

  以上都是通过线程来包装普通的函数。类的成员函数该如何引入线程呢?如下:

1)类外使用线程(推荐):

#include <iostream>
#include <thread> using namespace std; class ThreadTest
{
public:
ThreadTest()
{
cout<<"ThreadTest():"<<this<<endl;
}
void func()
{
int n = 0;
cout<<"void func(int n):"<<this<<endl;
while(n++<10)
{
cout<<"thread in class runtime:"<<n<<endl;
}
}
~ThreadTest() = default;
}; int main()
{
ThreadTest test;
thread t(&ThreadTest::func,test);
t.join();
cout<<"Pls observe the difference between the two printed addresses!"<<endl;return 0;
}

  这个函数执行起来显然没什么错误,但是有一个问题:我们构造时对象的内存地址居然与多线程中执行函数地址不一样,要记住这可是该对象的成员函数啊?我们前面已经提到过,不使用std::ref传入线程的变量默认都是以拷贝的方式传入的。两次地址不一样的原因就是如此!要想将该对象的成员函数加入线程,我们应该使用std::ref或者直接传入对象的指针。

#include <iostream>
#include <thread> using namespace std; class ThreadTest
{
public:
ThreadTest()
{
cout<<"ThreadTest():"<<this<<endl;
}
void func()
{
int n = 0;
cout<<"void func(int n):"<<this<<endl;
while(n++<10)
{
cout<<"thread in class runtime:"<<n<<endl;
}
}
~ThreadTest() = default;
}; int main()
{
ThreadTest test;
// thread t(&ThreadTest::func,test); //!对象拷贝
  thread t(&ThreadTest::func,std::ref(test));       //!传入引用
// thread t(&ThreadTest::func,&test); //!传入指针;
t.join();
cout<<"Please observe the difference between the two printed addresses!"<<endl;return 0;
}

2)类内使用线程:

#include <iostream>
#include <thread>
using namespace std; class ThreadInClass
{
public:
ThreadInClass(){cout<<"ThreadInClass():"<<this<<endl;}
~ThreadInClass() = default;
void runThread()
{
thread t(&ThreadInClass::func,this);
t.join();
// t.detach();//使用detach,同样也要保证runThread的生存周期比t要长。
}
void func()
{
int n = 0;
cout<<"void func(int n):"<<this<<endl;
while(n++<10){
cout<<"thread in class runtime:"<<n<<endl;
}
}
}; int main()
{
ThreadInClass tic;
tic.runThread();
}

Thread线程框架学习的更多相关文章

  1. JavaSE中线程与并行API框架学习笔记1——线程是什么?

    前言:虽然工作了三年,但是几乎没有使用到多线程之类的内容.这其实是工作与学习的矛盾.我们在公司上班,很多时候都只是在处理业务代码,很少接触底层技术. 可是你不可能一辈子都写业务代码,而且跳槽之后新单位 ...

  2. JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?

    前言:休整一个多月之后,终于开始投简历了.这段时间休息了一阵子,又病了几天,真正用来复习准备的时间其实并不多.说实话,心里不是非常有底气. 这可能是学生时代遗留的思维惯性--总想着做好万全准备才去做事 ...

  3. 学习接水系统(java+thread线程)

    (一)项目框架分析 对于学生并发接水项目,根据面向对象的思想,需要创建两个对象,即学生和水龙头. 接下来主要讲解不排队接水和排队接水两张情况. 项目的目录文件如下: (二)不排队接水 假设有四个学生小 ...

  4. Java线程池学习

    Java线程池学习 Executor框架简介 在Java 5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java ...

  5. 滴滴Booster移动APP质量优化框架 学习之旅

    推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 一.Booster简介 Booster是滴滴最近开源一个的移动应 ...

  6. Thread线程的基础知识及常见疑惑点

    引言 相信各位道友在平时工作中已经很少直接用到Thread线程类了,现在大多是通过线程池或者一些多线程框架来操作线程任务,但我觉得还是有必要了解清楚Thread线程类中各种方法的含义,了解了底层才能更 ...

  7. springboot日志框架学习------slf4j和log4j2

    springboot日志框架学习------slf4j和log4j2 日志框架的作用,日志框架就是用来记录系统的一些行为的,可以通过日志发现一些问题,在出现问题之后日志是好的一个帮手. 市面上的日志框 ...

  8. EF框架学习手记

    转载: [ASP.NET MVC]: - EF框架学习手记 1.EF(Entity Framework)实体框架EF是ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架 ...

  9. Struts2框架学习(二) Action

    Struts2框架学习(二) Action Struts2框架中的Action类是一个单独的javabean对象.不像Struts1中还要去继承HttpServlet,耦合度减小了. 1,流程 拦截器 ...

随机推荐

  1. python 2种创建多线程的方法

    多个线程是可以操作同一个全局变量的,因此,可以通过这种方式来判断所有线程的执行进度 # 第一种方法:将要执行的方法作为参数传给Thread的构造方法 import threading import t ...

  2. 【题解】Luogu P5339 [TJOI2019]唱、跳、rap和篮球

    原题传送门 这题zsy写的是\(O(n^2)\),还有NTT\(O(n^2\log n)\)的做法.我的是暴力,\(O(\frac{a b n}{4})\),足够通过 考虑设\(f(i)\)表示序列中 ...

  3. 移动端开发之响应式开发和bootstrap基础

    响应式开发 (就是利用媒体查询针对不同宽度的设备进行布局和样式的设置,从而设配不同设备的目的) 响应式布局容器响应式需要一个父级作为布局容器,来配合子级元素来实现变化效果 原理:不同屏幕下,通过媒体查 ...

  4. C#录制屏幕采集系统桌面画面

    在项目中,有很多需要录制屏幕的场景,比如直播课,录制教学视频等场景.但.NET自带的Screen类功能比较弱,效率很低.那么如何简单快捷地高效采集桌面屏幕呢?当然是采用SharpCapture!下面开 ...

  5. springCloud学习3(Netflix Hystrix弹性客户端)

    springcloud 总集:https://www.tapme.top/blog/detail/2019-02-28-11-33 本次用到全部代码见文章最下方. 一.为什么要有客户端弹性模式   所 ...

  6. printk打印级别

    默认级别 # cat /proc/sys/kernel/printk 4 4 1 7 分别是:控制台日志级别.默认的消息日志级别.最低的控制台日志级别和默认的控制台日志级别 举例 # echo 0 & ...

  7. js 高阶函数之柯里化

    博客地址:https://ainyi.com/74 定义 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且 ...

  8. Linux命令——pidof

    参考:Linux pidof Command Examples To Find PID of A Program/Command Linux pidof Command Tutorial for Be ...

  9. MySQL/MariaDB数据库的索引工作原理和优化

    MySQL/MariaDB数据库的索引工作原理和优化 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际工作中索引这个技术是影响服务器性能一个非常重要的指标,因此我们得花时间去了 ...

  10. PAT甲级1007题解——贪心

    题目分析:对于每一个点来说,如果选择合并入包含前一个点的序列那么只有在前一个点的序列不为负数(这里指的是包含前一个位置的数的一个连续序列的和不为负数),当前点才会将自己也加入这个子序列,否则,当前点则 ...