一个多线程面试题的解答

来源:互联网 发布:apache php mysql搭建 编辑:程序博客网 时间:2024/04/29 02:28

多线程的题目要求:

编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,
要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

备注:该面试题摘自http://blog.csdn.net/morewindows/article/details/7392749

解答思路:

定义三个事件,A事件用来触发线程A,B事件用来触发线程B,C事件用来触发线程C。初始化时,事件A设置为通知状态即执行线程A,并把事件B置为通知状态,同时也A事件复位。线程B等待B事件,事件通知就执行线程B,并把事件C置为通知状态,同时也B事件复位。线程C等待C事件,事件通知就执行线程C,并把事件A置为通知状态,同时也C事件复位。线程退出的条件为线程执行了10次。

下图为线程A、B、C的触发示意图:

以下为实现的代码:

#include "stdafx.h"
#include <wtypes.h>

#define DELAY_SECONDS   1000

//线程的入口参数
typedef struct tagThreadParam
{
 HANDLE hAEvent;
 HANDLE hBEvent;
 HANDLE hCEvent;
 DWORD dwThreadId;
}STThreadParam, *PSTThreadParam;

//线程A的处理函数
static UINT ThreadAProc(LPVOID pParam);
//线程B的处理函数
static UINT ThreadBProc(LPVOID pParam);
//线程C的处理函数
static UINT ThreadCProc(LPVOID pParam);

static int MultiThreadDemo(void);

//打印的最大次数
const int nMaxPrintNum = 10;

/*
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,
要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
*/

int _tmain(int argc, _TCHAR* argv[])
{
 int i = 0;

 MultiThreadDemo();

 scanf("%d", &i);

 return 0;
}

static int MultiThreadDemo(void)
{
 //线程句柄
 HANDLE hThreadA = NULL;
 HANDLE hThreadB = NULL;
 HANDLE hThreadC = NULL;
 //事件的句柄
 HANDLE hAEvent = NULL;
 HANDLE hBEvent = NULL;
 HANDLE hCEvent = NULL;
 //线程参数
 STThreadParam stThreadAParam;
 STThreadParam stThreadBParam;
 STThreadParam stThreadCParam;

 printf("MultiThreadDemo\n");

 hAEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 hBEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 hCEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

 stThreadAParam.dwThreadId = 0;
 stThreadAParam.hAEvent = hAEvent;
 stThreadAParam.hBEvent = hBEvent;
 stThreadAParam.hCEvent = hCEvent;
 stThreadBParam = stThreadAParam;
 stThreadCParam = stThreadAParam;

 hThreadA = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadAProc, (LPVOID)(&stThreadAParam),
  CREATE_SUSPENDED, NULL);
 hThreadB = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadBProc, (LPVOID)(&stThreadBParam),
  CREATE_SUSPENDED, NULL);
 hThreadC = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadCProc, (LPVOID)(&stThreadCParam),
  CREATE_SUSPENDED, NULL);

 SetEvent(hAEvent);
 ResumeThread(hThreadA);
 ResumeThread(hThreadB);
 ResumeThread(hThreadC);

 //必须要加延时,如果不加延时会得不到期望的输出结果
 Sleep(DELAY_SECONDS);

 CloseHandle(hAEvent);
 CloseHandle(hBEvent);
 CloseHandle(hCEvent);
 CloseHandle(hThreadA);
 CloseHandle(hThreadB);
 CloseHandle(hThreadC);

 return true;
}

//线程A的处理函数
static UINT ThreadAProc(LPVOID pParam)
{
 int nCount = 0;
 PSTThreadParam pThreadParam = NULL;

 if(pParam == NULL)
 {
  return false;
 }

 pThreadParam = (PSTThreadParam)pParam;
 while(true)
 {
  WaitForSingleObject(pThreadParam->hAEvent, INFINITE);

  nCount++;
  printf("ThreadA=%d\n", GetCurrentThreadId());
  if(nCount >= nMaxPrintNum)
  {
   SetEvent(pThreadParam->hBEvent);
   break;
  }

  ResetEvent(pThreadParam->hAEvent);
  SetEvent(pThreadParam->hBEvent);
 }

 return true;
}

//线程B的处理函数
static UINT ThreadBProc(LPVOID pParam)
{
 int nCount = 0;
 PSTThreadParam pThreadParam = NULL;

 if(pParam == NULL)
 {
  return false;
 }

 pThreadParam = (PSTThreadParam)pParam;

 while(true)
 {
  WaitForSingleObject(pThreadParam->hBEvent, INFINITE);

  nCount++;
  printf("ThreadB=%d\n", GetCurrentThreadId());
  if(nCount >= nMaxPrintNum)
  {
   SetEvent(pThreadParam->hCEvent);
   break;
  }

  ResetEvent(pThreadParam->hBEvent);
  SetEvent(pThreadParam->hCEvent);
 }

 return true; 
}

//线程C的处理函数
static UINT ThreadCProc(LPVOID pParam)
{
 int nCount = 0;
 PSTThreadParam pThreadParam = NULL;

 if(pParam == NULL)
 {
  return false;
 }

 pThreadParam = (PSTThreadParam)pParam;
 while(true)
 {
  WaitForSingleObject(pThreadParam->hCEvent, INFINITE);

  nCount++;
  printf("ThreadC=%d\n", GetCurrentThreadId());
  if(nCount >= nMaxPrintNum)
  {
   SetEvent(pThreadParam->hAEvent);
   break;
  }

  ResetEvent(pThreadParam->hCEvent);
  SetEvent(pThreadParam->hAEvent);
 }


 return true;
}

 

本代码已在VS2008上运行过。

原创粉丝点击