一、接口
ThreadPool(int minCapacity = 2,
int maxCapacity = 16,
int idleTime = 60,
int stackSize = POCO_THREAD_STACK_SIZE);
/// Creates a thread pool with minCapacity threads.
/// If required, up to maxCapacity threads are created
/// a NoThreadAvailableException exception is thrown.
/// If a thread is running idle for more than idleTime seconds,
/// and more than minCapacity threads are running, the thread
/// is killed. Threads are created with given stack size.
二、创建过程
ThreadPool::ThreadPool(int minCapacity,
int maxCapacity,
int idleTime,
int stackSize):
_minCapacity(minCapacity),
_maxCapacity(maxCapacity),
_idleTime(idleTime),
_serial(0),
_age(0),
_stackSize(stackSize)
{
poco_assert (minCapacity >= 1 && maxCapacity >= minCapacity && idleTime > 0);
for (int i = 0; i < _minCapacity; i++)
{
PooledThread* pThread = createThread();
_threads.push_back(pThread);
pThread->start();
}
}
void PooledThread::start()
{
_thread.start(*this);
_started.wait();
}
Thread::Thread():
_id(uniqueId()),
_name(makeName()),
_pTLS(0)
{
}
void Thread::start(Runnable& target)
{
startImpl(target);
}
void ThreadImpl::startImpl(Runnable& target)
{
if (isRunningImpl())
throw SystemException("thread already running");
_pRunnableTarget = ⌖
createImpl(runnableEntry, this);
}
void ThreadImpl::createImpl(Entry ent, void* pData)
{
#if defined(_DLL)
_thread = CreateThread(NULL, _stackSize, ent, pData, 0, &_threadId);
#else
unsigned threadId;
_thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);
_threadId = static_cast(threadId);
#endif
if (!_thread)
throw SystemException("cannot create thread");
if (_prio != PRIO_NORMAL_IMPL && !SetThreadPriority(_thread, _prio))
throw SystemException("cannot set thread priority");
}
ThreadPool pool(2, 3, 3);
三、它是如何动态管理所创建的线程?
RunnableAdapter ra(*this, &CThreadPoolTest::Count);
pool.start(ra); //!<用掉一个
void ThreadPool::start(Runnable& target)
{
getThread()->start(Thread::PRIO_NORMAL, target);
}
PooledThread* ThreadPool::getThread()
{
FastMutex::ScopedLock lock(_mutex);
if (++_age == 32)
housekeep();
PooledThread* pThread = 0;
for (ThreadVec::iterator it = _threads.begin(); !pThread && it != _threads.end(); ++it)
{
if ((*it)->idle()) pThread = *it;
}
if (!pThread)
{
if (_threads.size() < _maxCapacity)
{
pThread = createThread();
try
{
pThread->start();
_threads.push_back(pThread);
}
catch (...)
{
delete pThread;
throw;
}
}
else throw NoThreadAvailableException();
}
pThread->activate();
return pThread;
}
pThread->activate();
就是将空闲状态置为falsevoid PooledThread::activate()
{
FastMutex::ScopedLock lock(_mutex);
poco_assert (_idle);
_idle = false;
_targetCompleted.reset();
}
pool.addCapacity(1);
的方法,将最大线程数+1。void ThreadPool::addCapacity(int n)
{
FastMutex::ScopedLock lock(_mutex);
poco_assert (_maxCapacity + n >= _minCapacity);
_maxCapacity += n;
housekeep();
}
在我们增加最大线程数的同时,还执行了housekeep()函数:重新整理已有线程池,这边就涉及到自动清除空闲太久的线程方法:
void ThreadPool::housekeep()
{
_age = 0;
if (_threads.size() <= _minCapacity)
return;
ThreadVec idleThreads;
ThreadVec expiredThreads;
ThreadVec activeThreads;
idleThreads.reserve(_threads.size());
activeThreads.reserve(_threads.size());
for (ThreadVec::iterator it = _threads.begin(); it != _threads.end(); ++it)
{
if ((*it)->idle())
{
if ((*it)->idleTime() < _idleTime)
idleThreads.push_back(*it);
else
expiredThreads.push_back(*it);
}
else activeThreads.push_back(*it);
}
int n = (int) activeThreads.size();
int limit = (int) idleThreads.size() + n;
if (limit < _minCapacity) limit = _minCapacity;
idleThreads.insert(idleThreads.end(), expiredThreads.begin(), expiredThreads.end());
_threads.clear();
for (ThreadVec::iterator it = idleThreads.begin(); it != idleThreads.end(); ++it)
{
if (n < limit)
{
_threads.push_back(*it);
++n;
}
else (*it)->release();
}
_threads.insert(_threads.end(), activeThreads.begin(), activeThreads.end());
}
#pragma once
#include <assert.h>
#include "OutputDebugString.h"
#include "Poco/ThreadPool.h"
#include "Poco/RunnableAdapter.h"
#include "Poco/Exception.h"
#include "Poco/Thread.h"
#include "Poco/Event.h"
#include "Poco/Mutex.h"
using Poco::ThreadPool;
using Poco::RunnableAdapter;
using Poco::Thread;
class CThreadPoolTest
{
public:
CThreadPoolTest(): _count(0), _event(false){};
~CThreadPoolTest(){};
void Count()
{
_event.wait();
odprintf("Test run.....");
for (int i = 0; i < 10000; ++i)
{
_mutex.lock();
++_count;
//odprintf("values:%d", _count);
printf("values:%d\n", _count);
_mutex.unlock();
}
};
void Test()
{
ThreadPool pool(2, 3, 3); //!<创建个2线程的线程池,线程池最多拥有3个线程,在基本的2线程外的线程空闲时间超过3s,将被杀死
pool.setStackSize(1);
assert (pool.allocated() == 2); //!<判断当前是不是只有2线程
assert (pool.used() == 0); //!<判断当前是否线程在工作
assert (pool.capacity() == 3); //!<判断最大的线程数
assert (pool.available() == 3);
pool.addCapacity(1);
assert (pool.allocated() == 2);
assert (pool.used() == 0);
assert (pool.capacity() == 4);
assert (pool.available() == 4);
RunnableAdapter ra(*this, &CThreadPoolTest::Count);
pool.start(ra); //!<用掉一个
assert (pool.allocated() == 2);
assert (pool.used() == 1);
assert (pool.capacity() == 4);
assert (pool.available() == 3);
pool.start(ra); //!<用掉一个
assert (pool.allocated() == 2);
assert (pool.used() == 2);
assert (pool.capacity() == 4);
assert (pool.available() == 2);
pool.start(ra); //!<用掉一个
assert (pool.allocated() == 3);
assert (pool.used() == 3);
assert (pool.capacity() == 4);
assert (pool.available() == 1);
pool.start(ra); //!<用掉一个
assert (pool.allocated() == 4);
assert (pool.used() == 4);
assert (pool.capacity() == 4);
assert (pool.available() == 0);
try
{
pool.start(ra); //!<用掉一个,此时没有可用将发生异常
odprintf("thread pool exhausted - must throw exception");
}
catch (Poco::NoThreadAvailableException&)
{
odprintf("NoThreadAvailable exception thrown");
}
catch (...)
{
odprintf("wrong exception thrown");
}
_event.set(); // go!!! Run 开始执行循环
pool.joinAll(); //!<等待所有线程完成
assert (_count == 40000); //!<4个线程在累加,总的值为4W
//!<所有线程全部退出了
assert (pool.allocated() == 4);
assert (pool.used() == 0);
assert (pool.capacity() == 4);
assert (pool.available() == 4);
Thread::sleep(4000);
pool.collect(); //!<开始回收了,最终只会剩下2个线程
assert (pool.allocated() == 2);
assert (pool.used() == 0);
assert (pool.capacity() == 4);
assert (pool.available() == 4);
_count = 0;
_event.reset(); //!
pool.start(ra); //!<用掉一个
assert (pool.allocated() == 2);
assert (pool.used() == 1);
assert (pool.capacity() == 4);
assert (pool.available() == 3);
pool.start(ra); //!<用掉一个
assert (pool.allocated() == 2);
assert (pool.used() == 2);
assert (pool.capacity() == 4);
assert (pool.available() == 2);
_event.set(); // go!!!
pool.joinAll();
assert (_count == 20000);
assert (pool.allocated() == 2);
assert (pool.used() == 0);
assert (pool.capacity() == 4);
assert (pool.available() == 4);
};
private:
Poco::Event _event;
Poco::FastMutex _mutex;
int _count;
};