// MyThreadCase.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
#include "thread"
#include "windows.h"
#include "mutex"
using namespace std;
class CObject
{
public:
void operator ()() {
// 次数是对于()这一运算符重载,当对CObject类使用()时,调用
cout << "线程开始运行" << endl;
cout << "线程结束运行" << endl;
}
};
class myth
{
public:
volatile bool running = true;
int myid;
~myth()
{
printf("析构函数 %d\n",myid);
}
void recovery()
{
printf("回收资源 %d \n",myid);
}
std::mutex m; //注意,mutex不能拷贝,该对象后面不能用于值传递
void setpara(int myidd)
{
this->myid = myidd;
}
void stop()
{
m.lock();
this->running = false;
printf("线程 %d 准备停止 %s \n", myid, this->running);
m.unlock();
}
void operator ()() //不能带参数,可以另外给对象写初始化的参数
{
for (int i = 0; i < 400; i++)
{
m.lock();
bool temprun = this->running;
m.unlock();
//bool temprun = true;
if (temprun)
{
printf("—— %d —— %d-------%d-----\n", this->myid, i, GetCurrentThreadId()); // 获取线程id要include windows.h
Sleep(1);
}
else
{
printf("线程 %d 返回\n", myid);
break;
}
}
recovery();
}
};
int main()
{
//CObject obj;
//std::thread my2Obj(obj); // 主线程阻塞在这,并等待myPrint()执行完
//if (my2Obj.joinable()) {
// my2Obj.join();
//}
//cout << "see you " << endl;
printf(" 主线程id为 %d\n", GetCurrentThreadId()); // 获取线程id要include windows.h
myth obj1;
obj1.setpara(1);
myth obj2;
obj2.setpara(2);
myth obj3;
obj3.setpara(3);
thread t1(std::ref(obj1)); // 这样就不会调用拷贝构造函数,而是引用的形式
thread t2(std::ref(obj2));
thread t3(std::ref(obj3));
t1.detach();
t2.detach();
t3.detach();
Sleep(10);
obj1.stop();
obj2.stop();
obj3.stop();
/*t1.join();
t2.join();
t3.join();*/
system("pause");
return 0;
}
利用类对象创建线程,通过stop函数实现外部终止线程,线程内不断检查是否running为真,即可以运行,一旦为假,停止任务,线程函数最后要回收资源,注意 running 变量读写时需要加锁,否则内存访问错误,而mutex 为不可拷贝对象,之后应避免调用该类的拷贝构造函数,如值传递等,可以用std::ref()改为引用传递。最终运行的结果为:
注意,这里析构函数在system(“pause”)之后才会调用,所以资源回收最好单独写一个函数,在run函数结尾调用(或者说 每一个return之前),而不要直接卸载析构函数里面。