Google的多线程面试题
题目如下:
启动4个线程,向4个文件A,B,C,D里写入数据,每个线程只能写一个值。
线程1:只写1
线程2:只写2
线程3:只写3
线程4:只写4
4个文件A,B,C,D。
程序运行起来,4个文件的写入结果如下:
A:12341234...
B:23412341...
C:34123412...
D:41234123...
初次遇见这个题目的时候真是一头雾水,思维完全陷入了各种各样的锁操作中。最近在学习设计模式的时候(责任链模式),突发灵感。完全可以用这个模式的思想来解决这个问题,相当简单,一个锁都不需要。
比如我是线程A,我要做的事情很简单,就是往文件里面输出一个字符'1',然后通知线程2也去这个文件里面去输出他该输出的字符。现在责任很明确,唯一的问题就是该具体到哪个文件。把文件比喻成接力棒,当你收到这个接力棒的时候,输出字符,然后把接力棒传递给下一个人。其他3个线程也按照这个模式执行的话,那么整个责任链就形成了。然后每个线程该输出什么,该通知谁,我们可以在创建线程的时候就可以预先指定好。准备好以后,我们就可以将4个接力棒分给这几个线程。
#include <stdio.h>
#include <process.h>
#include <windows.h>
#include <fstream>
#include <string.h>
using namespace std;
fstream file1;
fstream file2;
fstream file3;
fstream file4;
HANDLE handles[4];
DWORD threadID[4];
#define WM_MY_NOTIFY (WM_USER + 1)
DWORD WINAPI ThreadProc(LPVOID lpParameter);
struct Task
{
string _text;// i know which text the thread need to print
fstream* _fp; //i don't know which file the thread need to print (Compilation phase)(no useful)
DWORD* _pThreadID2Notity;// i also know which thread should i need to notify
void runTask(fstream *fp) { // i know how to run my task
(*fp) << _text;
PostThreadMessage(*_pThreadID2Notity, WM_MY_NOTIFY, (WPARAM)fp, 0);
}
};
int main()
{
file1.open("1.txt", fstream::out | fstream::trunc);
file2.open("2.txt", fstream::out | fstream::trunc);
file3.open("3.txt", fstream::out | fstream::trunc);
file4.open("4.txt", fstream::out | fstream::trunc);
Task task[] = { {"1 ", NULL, threadID + 1},
{"2 ", NULL, threadID + 2},
{"3 ", NULL, threadID + 3},
{"4\n",NULL, threadID + 0}};
for (int i = 0; i < 4; i++)
{
handles[i] = CreateThread(NULL, // default security attributes
0, // use default stack size
ThreadProc, // thread function
(LPVOID)(task + i), // the task
0, // run right now
threadID + i); // returns the thread identifier
}
Sleep(1000); //the thread need some times to build message queue.
PostThreadMessage(threadID[0], WM_MY_NOTIFY, WPARAM(&file1), 0); //send baton 1
PostThreadMessage(threadID[1], WM_MY_NOTIFY, WPARAM(&file2), 0); //send baton 2
PostThreadMessage(threadID[2], WM_MY_NOTIFY, WPARAM(&file3), 0); //send baton 3
PostThreadMessage(threadID[3], WM_MY_NOTIFY, WPARAM(&file4), 0); //send baton 4
Sleep(5 * 1000);
for (int i = 0; i < 4; i++)
{
PostThreadMessage(threadID[i], WM_QUIT, 0, 0);
}
WaitForMultipleObjects(4, handles, true, INFINITE);
file1.close();
file2.close();
file3.close();
file4.close();
for (int i = 0; i < 4; i++)
{
CloseHandle(handles[i]);
}
return 0;
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
Task *pTask = (Task*)lpParameter;
MSG msg;
fstream *pfile = NULL;
while(GetMessage(&msg, NULL, 0, 0) != 0)
{
if (msg.message == WM_MY_NOTIFY)
{
pfile = (fstream*)msg.wParam; // get my baton
pTask->runTask(pfile);
}
Sleep(100);
}
return 1;
}
posted on 2013-06-20 17:46 MoreNotepad++ 阅读(455) 评论(0) 收藏 举报
浙公网安备 33010602011771号