1. 主线程和线程1在交替运行:
//因为我们要访问windows给我们提供的API函数,
//所以要包含一个windows.h文件
#include <windows.h>
#include <iostream.h>
//线程函数
DWORD WINAPI Fun1Proc(
LPVOID lpParameter
);
int index=0;
void main()
{
//当程序启动运行的时候,就会产生一个主线程,那么main()函数
//是作为主线程的入口函数。
HANDLEhThread1;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
//关闭线程的句柄,但是并没有终止我们新创建的线程
//我们应该在不再使用线程的句柄时候将其关闭掉,让这个线程的内核对象
//的引用计数-1
CloseHandle(hThread1);
while(index++<1000)
cout<<"main thread isrunning"<<endl;
//去指定一个时间间隔,在这个时间间隔内,线程是暂停运行的
//当它暂停执行的时候,就是它主动放弃了执行的机会
// Sleep(10);
}
DWORD WINAPI Fun1Proc(
LPVOID lpParameter
)
{
while(index++<1000)
cout<<"thread1 isrunning"<<endl;
return0;
}
//主线程在时间片之内运行,当时间片到期之后,操作系统会选择
//线程1开始运行,同样为线程1分配一个时间片,线程1运行一段
//时间之后,它的时间到期了,那么操作系统会选择主线程开始运行
//于是我们就可以看到主线程和线程1在交替运行。
//这就是主线程和线程1在单CPU平台下的交替运行,如果在多CPU中它们
//就可以真正的并发运行了。
2. 编写一个程序模拟火车站的购票系统:
火车站的购票系统是采用多线程实现的:
//因为我们要访问windows给我们提供的API函数,
//所以要包含一个windows.h文件
#include<windows.h>
#include<iostream.h>
//线程函数
DWORD WINAPIFun1Proc(
LPVOID lpParameter
);
DWORDWINAPI Fun2Proc(
LPVOID lpParameter
);
intindex=0;
inttickets=100;
//对于主线程来说,在这两个线程买完这100张票前,主线程不能退出
//如果这个主线程退出了,那么这个进程也就退出了,那么线程1和
//线程2也就跟着退出。
voidmain()
{
//当程序启动运行的时候,就会产生一个主线程,那么main()函数
//是作为主线程的入口函数。
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
//关闭线程的句柄,但是并没有终止我们新创建的线程
//我们应该在不再使用线程的句柄时候将其关闭掉,让这个线程的内核对象
//的引用计数-1
CloseHandle(hThread1);
CloseHandle(hThread2);
//让主线程睡眠4秒钟,当执行sleep的时候,主线程就放弃了它执行的权利
//进入等待状态,这个时间的主线程它是不占用CUP的执行时间的。
Sleep(4000);
}
DWORDWINAPI Fun1Proc(
LPVOID lpParameter
)
{
while(TRUE)
{
//做一个循环让线程不断的运行,不断地销售火车票
if(tickets>0)
{
Sleep(1);
cout<<"thread1sell ticket: "<<tickets--<<endl;
}
//如果票卖完了,则终止循环
else
break;
}
return 0;
}
DWORDWINAPI Fun2Proc(
LPVOID lpParameter
)
{
while(TRUE)
{
//做一个循环让线程不断的运行,不断地销售火车票
if(tickets>0)
{
Sleep(1);
cout<<"thread2sell ticket: "<<tickets--<<endl;
}
//如果票卖完了,则终止循环
else
break;
}
return 0;
}
线程的同步,利用这个函数可以创建一个互斥对象,利用这个互斥对象完成线程的同步。
3. 采用多线程技术编写一个网络聊天室程序:
BOOL CChatDlg::OnInitDialog()
{
InitSocket();
//定义一个指针,并给它分配空间
RECVPARAM*pRecvParam = new RECVPARAM;
//对结构体这两个当中的成员进行初始化
pRecvParam->sock= m_socket;
//所有跟窗口有关的类,都有一个数据成员叫m_hWnd,
//它保存了跟这个窗口类相关的句柄
pRecvParam->hwnd= m_hWnd;
//创建一个线程
HANDLEhThread = CreateThread( NULL, 0, RecvProc, (LPVOID)pRecvParam, 0, NULL);
//关闭线程句柄
CloseHandle(hThread);
returnTRUE; // return TRUE unless you set the focus to a control
}
//在InitSocket这个函数中,对套接字进行初始化
BOOL CChatDlg::InitSocket()
{
//数据报套接字
m_socket= socket( AF_INET, SOCK_DGRAM, 0);
if(INVALID_SOCKET== m_socket )
{
MessageBox("套接字创建失败!");
returnFALSE;
}
//定义一个地址结构体的变量
SOCKADDR_INaddrSock;
//然后对这个地址结构体的成员赋值
addrSock.sin_family= AF_INET;
addrSock.sin_port= htons(6000);
//让它接收发送到本地任意IP地址数据
addrSock.sin_addr.S_un.S_addr= htonl(INADDR_ANY);
//定义一个整型变量,让它接收bind的返回值
intretval;
retval = bind(m_socket, (SOCKADDR*)&addrSock, sizeof(SOCKADDR));
if( SOCKET_ERROR == retval )
{
//关闭套接字
closesocket(m_socket);
MessageBox("绑定失败");
returnFALSE;
}
return TRUE;
}
//线程函数
DWORD WINAPI CChatDlg::RecvProc(LPVOIDlpParameter)
{
//首先取出我们传入的两个参数值
SOCKETsock = ((RECVPARAM*)lpParameter)->sock;
HWNDhWnd = ((RECVPARAM*)lpParameter)->hwnd;
//接收数据
//在接收数据之前,定义一个套接字地址结构的变量
//它主要是用来接收发送端的地址信息
SOCKADDR_IN addrFrom;
//主要是接收返回的地址结构体的长度,这个变量要初始化
intlen = sizeof(SOCKADDR);
//字符数组,用来接收到来的数据
charrecvBuf[200];
//用来存放格式化后的数据
chartempBuf[300];
//让接收线程可以不断的运行下去
intretval;
while(TRUE)
{
//retval用来接收recvfrom的返回值
retval= recvfrom(sock, recvBuf, 200, 0, (SOCKADDR*)&addrFrom, &len );
if(SOCKET_ERROR == retval )
break;
//如果没有错误,可以做一个格式化,将格式化中的数据放到tempBuf当中,
//取出发送端的IP地址,调用inet_ntoa将地址转化为点分十进制表示的字符串
sprintf(tempBuf, "%s说: %s",inet_ntoa(addrFrom.sin_addr), recvBuf );
//将数据传给对话框(可以采用发送消息的方式,将这个消息传给对话框)
::PostMessage(hWnd, WM_RECVDATA, 0, (LPARAM)tempBuf);
}
return0;
}
//3 消息响应函数的实现
void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
{
//定义一个对象,取出数据
CStringstr = (char*)lParam;
//定义一个对象,用来接收旧的数据
CStringstrTemp;
//获取文本
GetDlgItemText(IDC_EDI_RECV, strTemp );
//增加一个换行
str+= "\r\n";
//加上先前的数据
str+= strTemp;
SetDlgItemText(IDC_EDI_RECV,str );
}
//发送端
void CChatDlg::OnBtnSend()
{
//用来接收IP地址
DWORDdwIP;
//首先得到这个控件的CWnd指针
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
//得到IP之后,可以定义一个地址结构体的变量
SOCKADDR_INaddTo;
addTo.sin_family= AF_INET;
addTo.sin_port= htons(6000);
addTo.sin_addr.S_un.S_addr= htonl(dwIP);
//得到要发送的数据
CStringstrSend;
GetDlgItemText(IDC_EDIT_SEND,strSend);
sendto(m_socket,strSend, strSend.GetLength()+1, 0,
(SOCKADDR*)&addTo,sizeof(SOCKADDR));
SetDlgItemText(IDC_EDIT_SEND,"");
}