文章目录
1. 想法
通过一个对象来调用,这种方法可以看成是主线程调用一个对象,相当于只有一个主线程,没有子线程。而我们的本意是产生子线程,因此这种方法是不对的。
解决方法:把run函数设置成私有的。
//
/// @file Thread.h
/// @author xiekun(519686353@qq.com)
/// @date 2020-01-31 17:53:03
//
#include <iostream>
using std::cout;
using std::endl;
class MyThread
{
public:
void run()
{
//...
}
};
int main(void)
{
MyThread mythread;
mythread.run(); //这种写法是error的
return 0;
}
2. 一些要注意的地方
-
pthread_creat()
函数 创建线程- 第一个是 线程 id
- 第二个是 线程属性 一般写NULL
- 第三个是 这个线程要运行的程序
- 第四个是 一般写NULL 或者写 传给第三个的(void *)参数(详见后面代码)
-
include <stdlib.h>
随机数函数的头文件srand()
生成一个种子srand(clock())
获取每一刻的时间
-
include <unistd.h>
sleep(1)
睡1秒
-
使用工程文件makefile
- 有多个.cc文件需要一起编译,也可以使用(g++ *.cc -lpthread)同时编译.cc文件
3. 代码文件
其实不使用命名空间wd也可以 大家可以自行去实现
Thread.h 头文件
///
/// @file Thread.h
/// @author xiekun(519686353@qq.com)
/// @date 2020-01-31 17:53:03
///
#ifndef __THREAD_H__
#define __THREAD_H__
#include "Noncopyable.h"
#include <pthread.h>
#include <iostream>
namespace wd {
class Thread
: Noncopyable //这种写法是私有继承 不需要noncopyable的接口 他也没提供接口 所以私有
/*
* 派生类在赋值复制操作时,
* 如果自己没有定义相关操作的函数
* 则会调用父类的赋值复制操作函数
* 这样 使得该派生类无法进行赋值赋值操作
*
* Thread就变成了 具有对象语义的类 --> 不能被复制
*/
{
public:
Thread();
virtual ~Thread(); //有了虚函数run 析构函数就要设置成虚构的
void start(); //开启子进程
void join(); //回收子进程
bool isRunning() const { return _isRunning; }
private:
virtual void run() = 0; //(虚函数一般作为接口)这是线程要执行的任务
/*
* 这里要设置成static没有this指针
* thread.cc中调用thread_create的第三个参数需要的是void * 格式
* 如果不使用static 则返回值带有this指针
* 所以 需要改成静态函数
*
*/
static void * threadFunc(void *);
private:
pthread_t _pthid;
bool _isRunning;
};
}
#endif
Thread.cc 实现Thread.h头文件
///
/// @file Thread.cc
/// @author xiekun(519686353@qq.com)
/// @date 2020-01-31 18:12:05
///
#include "Thread.h"
namespace wd {
Thread::Thread()
: _pthid(0)
, _isRunning(false) {
}
Thread::~Thread() {
if (_isRunning) {
pthread_detach(_pthid);
_isRunning = false;
}
}
void Thread::start() {
/*
* 创建线程 第四个参数this传给threadFunc
* 作为threadFunc(void *)的参数 这个参数是void *类型的
*
*/
pthread_create(&_pthid, NULL, threadFunc, this);
_isRunning = true;
}
void Thread::join() {
if (_isRunning) {
pthread_join(_pthid, NULL);
_isRunning = false;
}
}
void * Thread::threadFunc(void * arg) {
/*需要把(void *)强转成(Thread*) */
Thread * p = static_cast<Thread *>(arg);
if (p)
p->run(); //虚函数的使用需要调用对象(表现多态虚函数机制 )
return NULL;
}
}
TestThread.cc 测试主程序
///
/// @file TestThread.cc
/// @author xiekun(519686353@qq.com)
/// @date 2020-01-31 21:42:22
///
#include "Thread.h"
#include <stdlib.h>
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
using std::unique_ptr;
class MyThread
: public wd::Thread { //bug1 wd::
public:
~MyThread() { cout << "~MyThread" << endl; }
private:
void run() override {
int cnt = 10;
srand(clock());
while (cnt--) {
int number = rand() % 100;
cout << "sub thread " << pthread_self()
<< ":getNumber = " << number << endl;
}
}
};
void test0() {
cout << "main thread " << pthread_self() << endl;
unique_ptr<wd::Thread> mythread(new MyThread());
mythread->start();
mythread->join();
}
void test1() {
cout << "11main thread " << pthread_self() << endl;
MyThread mythread;
mythread.start();
mythread.join();
// MyThread mythread2(mythread);
/*
* 这是一个复制操作 需要被禁止error
* 以前的解决办法是:
* 方法1.把赋值操作运算符放在private里面
* 方法2.=delete 赋值操作
* 本例中的方法:
* 写一个noncopyable类,mythread继承该类,详见Thread.h
*
* 派生类在赋值复制操作时,
* 如果自己没有定义相关操作的函数
* 则会调用父类的赋值复制操作函数
* 这样 使得该派生类无法进行赋值赋值操作
*
*/
}
int main () {
test1();
return 0;
}
Noncopyable.h 禁止赋值/复制操作
Thread.h继承
///
/// @file Noncopyable.h
/// @author xiekun(519686353@qq.com)
/// @date 2020-01-31 23:03:26
///
#ifndef __NONCOPYABLE_H__
#define __NONCOPYABLE_H__
namespace wd {
class Noncopyable {
/*
* 这个类不用生成对象
* 用抽象类的第二种形式:
* protected就可以了
*/
protected:
Noncopyable() {};
~Noncopyable() {};
Noncopyable(const Noncopyable &) = delete;
Noncopyable & operator=(const Noncopyable &) = delete;
};
}
#endif
makefile 工程文件
也可以不使用makefile:
有多个.cc文件需要一起编译,则可以使用(g++ *.cc -lpthread)同时编译.cc文件
INC_DIR:= ./
SRC_DIR:= ./
SRCS:= $(wildcard $(SRC_DIR)*.cc)
CC:= g++
CXXFLAGS:= -g -Wall $(addprefix -I, $(INC_DIR))
LIBS:= -lpthread
OBJS:= $(patsubst %.cc, %.o, $(SRCS))
BIN_EXE:= TestThread.exe
$(BIN_EXE):$(OBJS)
$(CC) -o $@ $^ $(CXXFLAGS) $(LIBS)
%.o:%.cc
$(CC) -o $@ -c $< $(CXXFLAGS) $(LIBS)
print:
@echo $(OBJS)
clean:
rm -rf $(OBJS) $(BIN_EXE)
来源:CSDN
作者:ACMer_Shadow
链接:https://blog.csdn.net/qq_24653023/article/details/104135017