我的进程从单个队列中读取需要发送到多个目的地的任务。 我们需要维护任务之间的顺序(即在00:00到达队列的任务需要在到达00:01的任务之前发送)因此我们不能使用线程池。每个目的地需要维护订单。
一种解决方案是为每个目标创建一个专用线程。主线程读取 队列中的任务,并根据目标找到正确的线程。
此解决方案存在一个问题:如果工作线程忙,主线程将保持阻塞状态,从而使系统变慢。我需要的是每个线程一个新的队列。主线程 将资源共享给队列,工作线程读取新队列以进行传入 消息...
我想与SO社区分享我的想法,我正在寻找一个接近我的C / C ++解决方案。是否有一个实现这种模型的库?
答案 0 :(得分:4)
你想要的设计相当简单;我想你可以编写你需要的代码,并在一两个小时内完成它。寻找第三方库实现这一点可能有点过头了(除非我误解了这个问题)。
特别是,对于每个'worker'线程,你需要一个FIFO数据结构(例如std :: queue),一个Mutex,以及一个'master'线程可以用来指示线程唤醒和检查的机制新消息的数据结构(例如,条件变量,或信号量,甚至是工作程序在读取时阻塞的套接字对,并且主服务器可以发送一个字节来唤醒工作人员)。
然后要将任务发送到特定的工作线程,主人会做这样的事情(伪代码):
struct WorkerThreadData & workerThread = _workerThreads[threadIndexIWantToSendTo];
workerThread.m_mutex.Lock();
workerThread.m_incomingTasksList.push_back(theNewTaskObject);
workerThread.m_mutex.Unlock();
workerThread.m_signalMechanism.SignalThreadToWakeUp(); // make sure the worker looks at the task list!
...每个工作线程都有一个这样的事件循环:
struct WorkerThreadData & myData = _workerThreads[myWorkerIndex];
TaskObject * taskObject;
while(1)
{
myData.m_signalMechanism.WaitForSignal(); // block until the main thread wakes me up
myData.m_mutex.Lock();
taskObject = (myData.m_incomingTasks.length() > 0) ? myData.m_incomingTasks.pop_front() : NULL;
myData.m_mutex.Unlock();
if (taskObject)
{
taskObject->DoTheWork();
delete taskObject;
}
}
这永远不会阻塞主线程(任何大量的时间),因为互斥锁只是由任何人非常短暂地保持。特别是,工作线程在处理任务对象时没有持有互斥锁。
答案 1 :(得分:2)
“需要维护秩序”只是直接说明无论你有多少线程,你都将按顺序执行任务。既然如此,你最好只用一个线程来处理请求。
如果的要求比那更宽松,你可以获得的东西 - 例如,如果一个目的地的所有任务都需要按顺序排列,但是对于不同的任务没有排序要求目的地。如果是这种情况,那么主队列的解决方案将任务发送到每个单独线程的输入队列听起来都非常好。
编辑:
动态指定线程/互斥锁的数量非常简单。例如,要从命令行获取数字,您可以对此顺序执行某些操作(暂时不进行错误和完整性检查):
std::vector<pthread_t> threads;
int num_threads = atoi(argv[1]);
threads.resize(num_threads);
for (int i=0; i<num_threads; i++)
pthread_create(&threads[i], NULL, thread_routine, NULL);