参考:《Linux c与c++一线开发实践》朱文伟 李建英
将书上代码敲了一下,存在这里以便后续开发参考
一、类std::thread常用成员函数
成员函数 | 说明 |
---|---|
thread | 构造函数 |
get_id | 获得线程ID |
joinable | 判断线程对象是否可结束 |
join | 阻塞函数,等待线程结束 |
native_handle | 用于获得与操作系统相关的原生线程句柄 |
swap | 线程交换 |
detach | 分离线程 |
二、线程的创建
1.批量创建线程
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <iostream>
#include <thread>
using namespace std;
void thfunc(int n){
cout<<"thfunc:"<<n<<endl;
}
int main(){
thread threads[5]; //批量定义5个线程对象,但此时不会执行
cout<<"create 5 threads-----\n";
for(int i=0;i<5;++i)
threads[i]=thread(thfunc,i+1); //此处执行线程函数
for(auto& t:threads)
t.join();
cout<<"All threads joined.\n"<<endl;
return EXIT_SUCCESS;
}
通过终端中间键入如下命令执行
g++ -o <文件名> <文件名>.cpp -lpthread -std=c++11
./<文件名>
2.创建一个线程,传多个参数给线程函数
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <iostream>
#include <thread>
using namespace std;
void thfunc(int n,int m,int *pk,char s[]){ //线程函数
cout<<"in thfunc:n="<<n<<",m="<<m<<",k="<<*pk<<"\nstr="<<s<<endl;
*pk= 5000;
}
int main(){
int n=110,m=200,k=5;
char str[]="hello world";
thread t(thfunc,n,m,&k,str); //创建线程并传入参数
t.join(); //等待线程对象t结束
cout<<"k="<<k<<endl;
return EXIT_SUCCESS;
}
3.把可连接线程转为分离线程
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <iostream>
#include <thread>
using namespace std;
void thfunc(int n,int m,int *pk,char s[]){ //线程函数
cout<<"in thfunc:n="<<n<<",m="<<m<<",k="<<*pk<<"\nstr="<<s<<endl;
*pk= 5000; //主线程会先于此改变生效前结束
}
int main(){
int n=110,m=200,k=5;
char str[]="hello world";
thread t(thfunc,n,m,&k,str); //创建线程并传入参数
t.detach();
cout<<"k="<<k<<endl;
pthread_exit(NULL);
cout<<"this line will not run"<<endl;
return EXIT_SUCCESS;
}
三、当前线程this_thread
1.让出CPU时间
实例:线程赛跑排名次
volatile 指出变量是随时可能发生变化的,每次使用它的时候必须从它的地址中读取,因而编译器生成的汇编代码会重新从它的地址读取数据。一般说来,volatile用在如下的几个地方:
- 中断服务程序中修改的供其它程序检测的变量需要加 volatile;
- 多任务环境下各任务间共享的标志应该加 volatile;
- 存储器映射的硬件寄存器通常也要加 volatile 说明,因为每次对它的读写都可能由不同意义;
引自https://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777432.html
#include <atomic> //用来定义原子操作
#include <iostream>
#include <thread>
using namespace std;
atomic<bool> ready(false); //定义全局变量,原子操作确保所有其他线程都不再同一时间内访问
void thfunc(int id){ //线程函数
while(!ready) //一直等待,直到主函数修改ready
this_thread::yield(); //让出自己时间片
for(volatile int i=0;i<1000000;++i)
{}
cout<<id<<",";
}
int main(){
thread threads[10]; //定义10个线程对象
cout<<"race of 10 threads that count to 1 million:\n";
for(int i=0;i<10;++i)
threads[i]=thread(thfunc,i); //启动线程,将i传入
ready = true;
for(auto& th:threads) th.join(); //等待10个线程全部结束
cout<<endl;
return EXIT_SUCCESS;
}
2.线程暂停
#include <iostream>
#include <thread>
#include <chrono>
#include <ctime>
#include <time.h>
#include <stddef.h>
using namespace std;
void getNowTime(){
timespec time;
struct tm nowTime;
clock_gettime(CLOCK_REALTIME,&time); //获取自1970到现在的秒
localtime_r(&time.tv_sec,&nowTime);
char current[1024];
printf(
"%04d-%02d-%02d %02d:%02d:%02d\n",
nowTime.tm_year+1900,
nowTime.tm_mon+1,
nowTime.tm_mday,
nowTime.tm_hour,
nowTime.tm_min,
nowTime.tm_sec);
}
int main(){
using std::chrono::system_clock;
std::time_t tt= system_clock::to_time_t(system_clock::now());
struct std::tm *ptm = std::localtime(&tt);
getNowTime(); //打印当前时间
cout<<"Waiting for the next minute to begin...\n";
++ptm->tm_min; //增加一分钟
ptm->tm_sec = 0; //秒数置0
this_thread::sleep_until(system_clock::from_time_t(mktime(ptm)));
//暂停执行到下一个整分时间
cout<<"Waiting for another five seconds...\n";
for(int i=0;i<5;++i){
cout<<i<<endl;
this_thread::sleep_for(std::chrono::seconds(1)); //暂停1秒
}
getNowTime(); //打印当前时间
return EXIT_SUCCESS;
}