65.9K
CodeProject 正在变化。 阅读更多。
Home

线程池实现

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.33/5 (6投票s)

2003年4月26日

2分钟阅读

viewsIcon

93882

downloadIcon

2673

一个简单的线程池。

引言

本文介绍了一个可重用的线程池类。它控制使用的线程数量到一个规定的水平,并将请求调度到线程池中的任何线程执行。

背景

在编写一个包含大量线程的应用程序时,我发现管理大量线程很困难。我认为应该将线程数量限制到一个特定水平,并将任务排队到线程。因此,我决定实现这个可重用的线程池类。

使用代码

  1. ThreadPool.cppThreadPool.h 插入到项目中。
  2. 项目设置
    • 在“项目”菜单上,单击“设置”。
    • 在“项目设置”对话框中,单击“C/C++”选项卡。
    • 从“类别”下拉列表中选择“代码生成”。
    • 从“使用运行时库”下拉列表中选择“多线程”。
    • 点击“确定”。
  3. 调用 Initialize() 并提供所需的线程数;默认值为 1。可以推荐线程和任务的最大数量。如果需要,任务列表的大小将增长。默认值为 24 个线程和 1024 个任务信息。
  4. 每当需要分配一个任务时,调用 AssignTask() 并提供客户端的 _cdecl 函数指针。
  5. 该函数将由线程池中的任何空闲线程执行。
  6. 如果需要同步 DATA 成员,则需要在客户端提交的函数中完成同步。
  7. 当需要增加/减少线程数时,只需再次调用 Initialize。不会发生资源/内存泄漏。当前线程完成执行后将被中止。
  8. 要销毁线程池,无需删除线程池对象,请调用 UnInitialize()。这将删除所有资源。如果线程仍在工作,在发布 WM_QUIT 消息并等待一小段时间后,它将终止所有线程。
  9. UnInitialize() 也在析构函数中调用。

在演示应用程序中,使用“工作”菜单将示例任务分配给线程池。

/* S A M P L E - C O D E*/
CMyTestView::CMyTestView()
{
    m_Pool.Initialize(10,  /* Required number of threads */ 
                    20,  /* Max threads expected; Default = 24*/ 
                    2000 /* Max tasks expected at a time; Default=1024 */); 
    // Now only 10 thread will be in the pool; 
    // Second param 20 is just for internal memory allocation.
}

void CMyTestView::OnFirstJob() 
{
    THREAD_POOL_TASK taskInfo = {TEST_DO_TASK1, DoFirstJob, LPVOID(this)};
    m_Pool.AssignTask(&taskInfo );
}

// task submitter second
void CMyTestView::OnSecondJob() 
{
    THREAD_POOL_TASK taskInfo = {TEST_DO_TASK2, DoSecondJob, LPVOID(this)};
    m_Pool.AssignTask(&taskInfo );
}

// Thread pool call back. - for first task
bool DoFirstJob(UINT taskId, LPVOID pData)
{
    CMyTestView *pView = (CMyTestView*)pData;
    return pView->DoJob(taskId);
}

// Thread pool call back. - for second task
bool DoSecondJob(UINT taskId, LPVOID pData)
{
    CMyTestView *pView = (CMyTestView*)pData;
    return pView->DoJob(taskId);
}

// Actual execution goes here.
bool CMyTestView::DoJob(UINT taskId)
{
    switch(taskId)
    {
        case TEST_DO_TASK1:
        {
            m_Message = _T("Doing FIRST job");
            Invalidate(0);
            int nCount = 1;
            while (nCount--)
            {
                Sleep(1000);    
                Beep(100, 1000);
            }
        }
        break;
        case TEST_DO_TASK2:
        {
            m_Message = _T("Doing SECOND job");
            Invalidate(0);
            int nCount = 2;
            while (nCount--)
            {
                Sleep(2000);    
                Beep(200, 2000);
            }
        }
    }
    return true;
}

void CMyTestView::OnResetWorkLoad() 
{
    m_Message = _T("On Reset Work Load");
    Invalidate(0);
    m_Pool.Initialize(5,   /* Required number of threads */  
            20,  /* Max threads expected; Default = 24*/ 
            2000 /* Max tasks expected at a time; Default=1024 */);    
    // Now only 5 thread will be in the pool; 
    // Out of previous TEN, FIVE will be removed.
}

关注点

我学习了线程池的用处。令人烦恼的是,回调函数需要全局函数。我通过在类中静态函数来管理它。

© . All rights reserved.