一、题目
(Google面试题)
有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,以此类推………现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
A:1 2 3 4 1 2….
B:2 3 4 1 2 3….
C:3 4 1 2 3 4….
D:4 1 2 3 4 1….
请设计程序。
二、思路
类似于在食堂开放四个窗口(线程)打饭,同学们(文件)排成循环队伍,交替的在各个窗口中打饭。如图:
每个同学(文件)对应一个菱形,当在对应的窗口打到饭后(即,线程输出对应的号码),队伍循环移动一位。整个过程,见下表:
一号窗口 | 二号窗口 | 三号窗口 | 四号窗口 |
---|---|---|---|
1 | 2 | 3 | 4 |
2 | 3 | 4 | 1 |
3 | 4 | 1 | 2 |
4 | 1 | 2 | 3 |
三、代码
#include <windows.h>
#include <iostream>
#include <fstream>
#include <thread>
#include <process.h>
using namespace std;
#define WRITECOUNT 1000
#define THREAD_COUNT 4
std::ofstream *files[THREAD_COUNT];
int hasResolveCount = 0;
CRITICAL_SECTION g_cs;
HANDLE g_event[THREAD_COUNT];
HANDLE threads[THREAD_COUNT];
void ShiftFiles();
void TriggerEvent(int n);
unsigned int _stdcall fun(LPVOID arg)
{
int id = int(arg);
int i = 0;
while(i<WRITECOUNT)
{
WaitForSingleObject(g_event[id],INFINITE);
*files[id] << id+1;
EnterCriticalSection(&g_cs);
++hasResolveCount;
++i;
if( hasResolveCount >= THREAD_COUNT && i<WRITECOUNT )
{
hasResolveCount = 0;
ShiftFiles();
TriggerEvent( THREAD_COUNT + 1 );
}
LeaveCriticalSection(&g_cs);
}
//cout << "ID " << id+1 << " over" << endl;
return 0;
}
void TriggerEvent(int n)
{
if(n > THREAD_COUNT)
{
for(int i = 0; i<THREAD_COUNT; ++i)
{
SetEvent(g_event[i]);
}
}
else if(n > 0 && n<=THREAD_COUNT)
{
SetEvent(g_event[n-1]);
}
}
void InitialEvent()
{
for(int i = 0; i<THREAD_COUNT; ++i)
{
g_event[i] = CreateEvent(NULL ,false ,false ,NULL);
}
}
void SetFiles()
{
char filename[] = "A.txt";
for(int i = 0; i<THREAD_COUNT; ++i)
{
cout << "file: " << i << endl;
filename[0] = 'A' + i;
files[i] = new ofstream( );
files[i]->open(filename);
}
}
void ReleaseFiles()
{
for(int i = 0; i<THREAD_COUNT; ++i)
{
delete files[i];
}
}
void ShiftFiles()
{
ofstream *temp = files[ THREAD_COUNT - 1 ];
for(int i = THREAD_COUNT - 2; i>=0; --i)
{
files[i+1] = files[i];
}
files[ 0 ] = temp;
}
int main()
{
SetFiles();
InitialEvent();
InitializeCriticalSection(&g_cs);
for(int i = 0; i<THREAD_COUNT; ++i)
{
threads[i] = (HANDLE)_beginthreadex(NULL,0,fun,(LPVOID)i,0,NULL);
}
TriggerEvent(THREAD_COUNT + 1);
WaitForMultipleObjects(THREAD_COUNT,threads,true,INFINITE);
for (int i = 0; i<THREAD_COUNT; ++i)
{
CloseHandle(g_event[i]);
CloseHandle(threads[i]);
}
ReleaseFiles();
DeleteCriticalSection(&g_cs);
return 0;
}