我在Ubuntu上使用posix在c ++中编写了一个简单的线程池,它从Code :: Blocks开始编译并按预期运行。但是,当我从终端执行程序时,它会在第一个线程任务完成后挂起。
以下是任务对象的execute()函数中的代码:
void TestTask::execute()
{
FILE* file;
std::string fname = "output";
char n = (char)m_id;
fname+=n;
fname+=".txt";
file = fopen(fname.c_str(), "w");
for (int i = 0; i < 10; i++)
{
fprintf(file,"Thread ID: %d, count : %d\n", m_id, i);
}
fclose(file);
}
如您所见,代码只是将一些数据输出到每个线程的单独文件中。
我也尝试过:
void TestTask::execute()
{
for (int i = 0; i < 10; i++)
{
printf("Thread ID: %d, count : %d\n", m_id, i);
}
}
如前所述,当项目构建并在code :: blocks中运行时,这两个版本都可以正常工作,但是当从命令行运行可执行文件时,它会挂起。
线程池代码:
ThreadPool::ThreadPool(int iNumThreads):mRunning(false), mShuttingDown(false)
{
mThreads.resize(iNumThreads);
if(iNumThreads > 0)
for (int i = 0; i < iNumThreads; i++)
{
pthread_create(&mThreads[i], NULL, ThreadPool::ThreadFunc,(void*) this);
}
pthread_mutex_init(&mMemLock, NULL); //mutex' are initialised unlocked.
}
void ThreadPool::stop()
{
pthread_mutex_lock(&mMemLock);
mRunning = false;
pthread_mutex_unlock(&mMemLock);
}
void ThreadPool::start()
{
//signal all threads to wake up and start extracting tasks to execute.
if(!mTasks.empty())
pthread_cond_broadcast(&mConditionSignal);
mRunning = true;
}
bool ThreadPool::shutDown()
{
//terminate all threads, regardless of status. Brute force approach, only to be used in race conditions or major errors.
for (size_t i = 0; i < mThreads.size();i++)
{
int err = pthread_cancel(mThreads[i]);
if(err != 0)
return false;
}
return true;
}
bool ThreadPool::shutDownClean()
{
//set flag and wait for all threads to terminate normally
mShuttingDown = true;
for(size_t i = 0; i < mThreads.size();i++)
{
pthread_join(mThreads[i], NULL);
}
return true;
}
bool ThreadPool::addTask(Task* pTask, bool start)
{
mTasks.push_back(pTask);
if(start)
{
mRunning = true;
pthread_cond_signal(&mConditionSignal);
}
return true;
//wake up a single thread to deal with a single task (first come, first served)
}
void ThreadPool::addCompleteTask(Task* pTask)
{
mCompletedTasks.push_back(pTask);
}
Task* ThreadPool::getNextCompletedTask()
{
Task* t = mCompletedTasks.front();
mCompletedTasks.pop_front();
return t;
}
Task* ThreadPool::getNextScheduledTask()
{
Task* t = mTasks.front();
mTasks.pop_front();
return t;
}
bool ThreadPool::isRunning()
{
return (mRunning);
}
ThreadPool::~ThreadPool()
{
if(!mShuttingDown)
shutDownClean();
mThreads.clear();
mTasks.clear();
mCompletedTasks.clear();
}
void* ThreadPool::ThreadFunc(void* ptr)
{
ThreadPool *pool = (ThreadPool*)ptr;
Task *task;
//infinite do nothing loop. The thread will spin it's wheels while it waits for work.
while(true)
{
pthread_mutex_lock(&pool->getMutex());
while(pool->isRunning() && !pool->hasCurrentTasks())
{
//wait on signal from pool to begin
pthread_cond_wait(&pool->getCondition(), &pool->getMutex());
}
//If the pool has tasks needing executed
if(pool->hasCurrentTasks())
{
//get the task and execute it, after unlocking the mutex
task = pool->getNextScheduledTask();
pthread_mutex_unlock(&pool->getMutex());
task->execute();
//if the task has return data, then add it to the list of completed tasks, for the main thread to evaluate
if(task->hasReturnData())
{
pthread_mutex_lock(&pool->getMutex());
pool->addCompleteTask(task);
pthread_mutex_unlock(&pool->getMutex());
}
//if not, we need not keep the task object any more
else
delete task;
}
else
{
//stop the pool running, and unlock the mutex
pool->stop();
pthread_mutex_unlock(&pool->getMutex());
}
if(pool->isShuttingDown())
{
break;
}
}
pthread_exit(NULL);
}
以下是main.cpp的代码:
int main(int argc, char** argv)
{
int numCores = sysconf(_SC_NPROCESSORS_ONLN);
ThreadPool* pool = new ThreadPool(numCores);
for (int i = 0; i < numCores; i++)
{
if(!pool->addTask(new TestTask(i)))
pool->shutDown();
}
pool->start();
if(!pool->shutDownClean())
return 1;
else
return 0;
}