3

boost::thread_group用来创建(使用 thread_group::create_thread())和调度线程。为了限制最大线程数,在每个线程结束时,我从线程中thread_group删除线程并删除线程本身(以便我可以决定是否需要创建新线程)。然而,它在最后一个线程的创建和删除之间挂起(比如总共 999 个线程中的第 999 个)。

我的问题是:

  • 可以像我一样从内部删除线程吗?如果没有,实现这一目标的最佳方法是什么
  • 为什么我的代码挂起?

下面是相关代码:

//1- 创建和调度线程的代码

 { 
        //mutex for map<thread_id, thread*> operations 
        boost::mutex::scoped_lock lk(m_mutex_for_ptr); 

        // create a thread for this->f(duplicate_hashes) 
        boost::thread* p = m_thread_group.create_thread(boost::bind( 
            &detectiveT<equal_predicate>::f, 
            this, 
            duplicate_hashes 
            )); 

        // save the <thread_id,thread pointer> map for later lookup & deletion 
        m_thread_ptrs.insert(make_pair(p->get_id(), p)); 

        // log to console for debug 
        cout << "thread created: " 
            << p->get_id() << ", " 
            << m_thread_group.size() << ", " m_thread_ptrs.size() << 
"\n";     
    }   

//2-线程执行代码

void f(list<map_iterator_type>& l) 
{ 
    Do_something(l);    
    boost::this_thread::at_thread_exit(boost::bind( 
        &detectiveT<equal_predicate>::remove_this_thread, 
        this 
        ));                     
} 

//3- 删除线程本身的代码

void remove_this_thread() 
{ 

    { 
        //mutex for map<thread_id, thread*> operations 
        boost::mutex::scoped_lock lk(m_mutex_for_ptr);                   
        boost::thread::id this_id(boost::this_thread::get_id()); 

        map<boost::thread::id, boost::thread*>::iterator itr; 

        itr = (m_thread_ptrs.find(this_id)); 

        if(m_thread_ptrs.end() != itr) 
        { 
            // remove it from the control of thread_group 
            m_thread_group.remove_thread(itr->second); 
            // delete it 
            delete itr->second; 

            // remove from the map 
            m_thread_ptrs.erase(this_id); 

            // log to console for debug 
            cout << "thread erased: " 
                << this_id << ", " 
                << m_thread_group.size() << ", " 
                << m_thread_ptrs.size() << "\n";             
        } 
    }               
}
4

1 回答 1

4

为什么不尝试回收线程,因为创建/销毁很昂贵?

编写一个线程池类并向其发送任务。如果没有更多可用线程,池将排队任务,如果 current_threads < max_threads 则创建线程,或者只使用可用的线程。

建议实施:

找出您理想的线程数是多少。这通常等于处理器的数量。根据您希望这有多复杂,您可以一次创建池中的所有线程,或者如果 current-thread-count < Ideal-thread-count 并且所有现有线程都忙于执行任务,则添加线程。

假设您一次创建所有线程,您需要将一个工作函数传递给每个线程以执行。这个工作函数将等待任务变得可用,然后执行它们。因为函数要么执行一个任务,要么等待它,它不会返回,线程也不会被销毁

线程池可以跟踪任务队列并管理指示队列中何时有可用任务的等待条件。每个线程工作者函数等待等待条件,当有可用的任务时,它会唤醒并尝试执行任务。您将不得不进行一些同步;最简单的方法是尝试找到一个可用的线程池实现,比如 Windows 中的那个(我认为是 Vista+)或 QtConcurrent 中的那个,它允许你传递任务,调用 run 并让操作系统/库担心一切。

后期编辑:

查看http://threadpool.sourceforge.net/

于 2009-08-19T13:04:32.227 回答