/*基于接口思想创建线程对象*/
#include<iostream>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
//接口只需要留下基本的框架,内容有派生去完成,也就是接口留下最基本的共性
/*===============功能体接口(不受执行体是线程还是进程,功能体的派生必须可以给这两种执行体对象利用,从而减少耦合度)=====================*/
int i=0;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//声明并初始化互斥量,也可用pthread_mutex_init(&mutex,NULL);来初始化。
class whatfuntion
{
public:
whatfuntion()
{
}
virtual ~whatfuntion()
{
}
public:
virtual void* exactfuntion(void* w_val=NULL)
{
}
};
/*==================执行体接口(可以派生出进程对象和线程对象,而且可以利用到功能体的对象)=====================*/
class ZXtype
{
public:
ZXtype(whatfuntion *funtion)//型参是基类指针,实参是派生类指针,从而完成多态
{
ZXtype_exact_funtion=funtion;//执行体要实习什么功能,从而把功能对象的指针赋予它
}
virtual ~ZXtype()
{
}
virtual int ZXtype_run(void* val=NULL)//执行体虚函数,可以在派生中重写,让对象为线程执行体或进程执行体
{
}
virtual int ZXtype_wait()//等待,派生中根据要派生出线程还是进程来重写为线程等待还是进程等待
{
}
protected:
whatfuntion * ZXtype_exact_funtion;//功能对象的指针(ZXtype派生对象的指针作为执行体对象的构造函数的参数)
};/*=============派生线程==========================
*/
class pthread:public ZXtype
{
public:
pthread(whatfuntion *funtion):ZXtype(funtion)
{
}
virtual ~pthread()
{
}
int run(void *val=NULL)//创建线程
{
m_val=val;
int err;
err=pthread_create(&n_pthread_id,NULL,ZXtype_funtion,this);//this指针为参数,但其不是功能函数的参数,而是线程在主函数要跳转到功能函数的使命
if(err!=0)
{
std::cout<<"pthread_create is fail,"<<strerror(err)<<std::endl;
return 0;
}
return 0;
}
int wait()//主线程调用wait中的pthread_join等待线程返回,同时打印线程的返回值
{
void* return_val;
int err=pthread_join(n_pthread_id,&return_val);//pthread_wait中接受返回值的参数必须是void**,但取出返回值内容为void*
if(err!=0)
{
std::cout<<"pthread_join is fail,"<<strerror(err)<<std::endl;
return 0;
}
std::cout<<"*"<<((int)return_val)<<"_pthread successful over"<<std::endl;//以“返回值_pthread successful over"打印返回值
”
return 0;
}
private:
static void* ZXtype_funtion(void* val)//线程的主函数(必须为void* (*)(void*)类型的普通函数,所以要用static把成员函数变成普通函数)
{
pthread * pthread_this=(pthread*)val;
void *return_val=pthread_this->ZXtype_exact_funtion->exactfuntion(pthread_this->m_val);//this参数作用:找到对象本身的接受的功能对 //象的指针即ZXtype_exact_funtion
return (return_val);//返回值
}
private:
pthread_t n_pthread_id;
private:
void *m_val;//传给功能函数的参数必须是公有的
};
/*=====================派生功能体(不受执行体是哪种类型都可以利用)=======================
此功能完成i由0自增到500000,并最终打印出i的最终值与线程id。(期间用到互斥量,否则i++会在多线程中出现混乱)
*/
class myfuntion :public whatfuntion
{
public:
myfuntion()
{
}
~myfuntion()
{
}
protected:
void* exactfuntion(void * w_val)
{
pthread_mutex_lock(&mutex)//参数为指向互斥量的指针
pthread_t pthreadid=pthread_self();//获取线程的id
for(int j=5000000;j>0;j--)
{
(i)++;
/*注意:
互斥量保护多线程访问的共享变量(也就是全局变量,这里的局部变量j不是共享的,因为多线程访问局部变量会有自己的备份)
听说java环境下,局部结构体变量是共享的,而Linux下g++的C++没发现此问题。
互斥量必须为共享的(即全局变量)才可实现互斥
*/ }
std::cout<<std::hex<<((int)(w_val))<<"_pthread: pth_ID="<<pthreadid<<" ----- i="<<std::dec<<i<<std::endl;//打印传过来的参数
pthread_mutex_unlock(&mutex);
//sleep(3);//测试wait是否等待线程返回
return w_val;
}
};
/*总结几点,
1.线程之间参数传递一定是void*型,所以传递之前必须把自己要传的参数强制转换成void*型。而且参数只能有一个,需要多个参数时可用一个结构体指针实现。
2.把执行体和功能分开可以减少两者的耦合度(也可把功能虚函数放在线程类中,在派生中重写,这就是面对对象思想,当这个功能函数只能为线程使用,而上面的接口思想可 以被任何对象使用,如进程体)
*/