如何使用批次相同的线程池批 [英] How to use the same thread pool batch by batch

查看:137
本文介绍了如何使用批次相同的线程池批的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了一个提升基于线程池的良好的执行这是一种进步了和<一个href=\"http://think-async.com/Asio/Recipes?skin=clean.nat,asio,pattern#A_thread_pool_for_executing_arbi\"相对=nofollow>这个。这是很容易理解和测试。它看起来是这样的:

 的#include&LT;升压/线程/ thread.hpp&GT;
#包括LT&;升压/ asio.hpp&GT;
//实际的线程池
结构线程池{
   线程池(的std ::为size_t);
   模板&LT;类F&GT;
   无效排队(F F);
   〜线程池();   //我们包装io_service对象
   提高:: ASIO :: io_service对象io_service对象;
   //不要让io_service对象停止
   提高:: shared_ptr的&LT;提高:: ASIO :: io_service对象::工作&GT;工作;
   //线程
   提高:: thread_group线程;
};//构造刚刚推出一些工人数量
线程池::线程池(为size_t确定nthreads)
   :io_service对象()
   ,工作(新的boost ::支持ASIO :: io_service对象::工作(io_service对象))
{
   对于(的std ::为size_t我= 0; I&LT;确定nthreads ++我){
    threads.create_thread(提高::绑定(安培;提高:: ASIO :: io_service对象::来看,&安培; io_service对象));
   }
}//添加新的工作项目池
模板&LT;类F&GT;
无效线程池::排队(F F){
   io_service.post(F);
}//析构函数加入的所有主题
线程池::〜线程池(){
work.reset();
io_service.run();
}//测试仪:
无效F(int i)以
{
    性病::法院LT&;&LT; 你好&LT;&LT; I&LT;&LT;的std :: ENDL;
    提高:: this_thread ::睡眠(升压::了posix_time ::毫秒(300));
    性病::法院LT&;&LT; 世界&LT;&LT; I&LT;&LT;的std :: ENDL;
}//它可以通过进行测试:诠释主(){
   //创建的4个工作线程的线程池
   线程池池(4);   //排队一堆工作项目
   的for(int i = 0; I&LT; 8; ++ I){
      性病::法院LT&;&LT; 任务&LT;&LT; I&LT;&LT; 创造&LT;&LT;的std :: ENDL;
      pool.enqueue(提高::绑定(安培; F,I));
   }
}

G ++线程池,4.cpp -lboost_system -lboost_thread

现在的问题是:
我需要知道我怎么能修改实现能够通过分批使用此线程池批次只在第一盘我的工作完全由线程池完成,我需要提供第二组等等。我试着用 .RUN() .reset段()之间(在析构函数中)批处理作业玩但没有运气:

  //添加方法胎面池:
//重新设置ASIO工作和线程
无效线程池::复位(为size_t确定nthreads){work.reset(新的boost ::支持ASIO :: io_service对象::工作(io_service对象));
   对于(的std ::为size_t我= 0; I&LT;确定nthreads ++我){
    threads.create_thread(提高::绑定(安培;提高:: ASIO :: io_service对象::来看,&安培; io_service对象));
   }
    性病::法院LT&;&LT; 组大小:&LT;&LT; threads.size()&所述;&下;的std :: ENDL;
}//加入,甚至,中断
无效线程池:: joinAll(){
  threads.join_all();
  threads.interrupt_all();
}//测试仪
诠释主(){
   //创建的4个工作线程的线程池
   线程池池(4);   //排队一堆工作项目
   的for(int i = 0; I&LT; 20; ++ I){
      性病::法院LT&;&LT; 任务&LT;&LT; I&LT;&LT; 创造&LT;&LT;的std :: ENDL;
          pool.enqueue(提高::绑定(安培; F,I));
   }
   //在这里,我与ASIO工作,io_service对象和和线程组玩
   pool.work.reset();
   pool.io_service.run();
   性病::法院LT&;&LT; &LT运行后;&LT;的std :: ENDL;
   pool.joinAll();
   性病::法院LT&;&LT; 后加入所有的&LT;&LT;的std :: ENDL;
   pool.reset(4);
   性病::法院LT&;&LT; 新的线程组大小:&LT;&LT; pool.threads.size()&所述;&下;的std :: ENDL; /// BTW:新threa组大小为8。我预期的4!
    //第二批...永远不会完成
   对于(INT I = 20; I&LT; 30; ++ I){
          pool.enqueue(提高::绑定(安培; F,I));
   }
}

第二批没有完成。我将AP preciate如果你能帮我解决这个问题。
谢谢

更新 - 解决方案:

基于的解决方案

,我开发利用条件变量的解决方案。只需添加以下code原班:

  //新的工作项目添加到池
模板&LT;类F&GT;
无效线程池::排队(F F){
    {
        提高:: unique_lock&LT;提高::互斥&GT;锁定(mutex_);
        nTasks ++;
    }
    //转发工作,包装()
    无效(线程池:: * FF)(升压::元组LT; F&GT;)=&安培;线程池::包装&LT; F&GT ;;
    io_service.post(升压::绑定(FF,这一点,提振:: make_tuple(F))); //使用一个元组似乎是唯一可行的方法。它是在升压实施例中提及。
}
//运行+ notfiy
模板&LT;类F&GT;
无效线程池::包装(升压::元组LT; F&F)的温度{
    提高::获得℃的&GT;(六)(); //这是任务(函数及其参数),有由一个线程来执行
    {
        提高:: unique_lock&LT;提高::互斥&GT;锁定(mutex_);
        nTasks - ;
        cond.notify_one();
    }
}无效线程池::等待(){
    提高:: unique_lock&LT;提高::互斥&GT;锁定(mutex_);
    而(nTasks){
        cond.wait(锁);
    }
}

现在你可以叫等待()工作批次之间的方法。
但是一个问题:
即使是最后一批之后,我得叫 pool.wait()是因为线程池的范围将后和线程池的析构函数将被调用结束。在破坏,有些作业完成,这将是打电话的时间 .notify()。由于线程池::破坏时互斥无效,锁定期间发生异常。您的建议将是AP preciated。


解决方案

一个条件变量可以被用来实现期望的结果。

实施负责召集入队的任务和等待条件变量的函数。
在分配给池中的所有任务完成条件变量被通知。

每个线程检查作业完成与否。一旦所有的作业完成条件变量被通知。

  //一个你可以尝试什么样的例子,这只是什么可以探讨的一个提示。     无效的jobscheduler()
    {
      诠释工作= numberOfJobs; //这可能会发生变化,并且可以由共享存储器       //排队一堆工作项目
       的for(int i = 0; I&LT;岗位; ++ I)
       {
          性病::法院LT&;&LT; 任务&LT;&LT; I&LT;&LT; 创造&LT;&LT;的std :: ENDL;
          pool.enqueue(提高::绑定(安培; F,I));
       }
       //等待条件变量
      提高::互斥:: scoped_lock的锁(the_mutex);
      conditionVariable.wait(锁); //有这种varibale从中意识到,所有的工作都完成任何线程通知。
     }


解决方案2

我有一个新的有效的解决方案,与有关职能语法一些假设被称为回来,但可以改变按要求。

继续对上述我使用条件变量来管理我的任务,但有区别的线条。


  1. 创建一个任务队列。

  2. 这等待队列中的新的就业机会的经理。

  3. 一旦工作收到通知发送到等待差不多的经理。

  4. 工人维持一个句柄经理。当分配的所有任务已完成经理被告知。

  5. 在获得最终的电话,经理停止等待队列中并退出新的就业机会。


 的#include&LT;&iostream的GT;
#包括LT&;&队列GT;
#包括LT&;升压/线程/ thread.hpp&GT;
#包括LT&;升压/ asio.hpp&GT;
#包括LT&;升压/元组/ tuple.hpp&GT;
#包括LT&;升压/元组/ tuple_io.hpp&GT;
#包括LT&;升压/ function.hpp&GT;///作业队列坚持要求执行的所有作业
模板&LT; typename的工作&GT;
类JobQueue
{
  私人的:    的std ::队列&LT;人才与GT; _队列;
    可变的boost ::互斥_mutex;
    提高:: condition_variable _conditionVariable;  上市:
    无效的push(const的工作和放大器;工作)
    {
      提高::互斥:: scoped_lock的锁(_mutex);
      _queue.push(工作);
      lock.unlock();
      _conditionVariable.notify_one();
    }    bool的空()const的
    {
      提高::互斥:: scoped_lock的锁(_mutex);
      返回_queue.empty();
    }    布尔tryPop(工作和放大器; poppedValue)
    {
      提高::互斥:: scoped_lock的锁(_mutex);
      如果(_queue.empty())
      {
        返回false;
      }      poppedValue = _queue.front();
      _queue.pop();
      返回true;
    }    无效waitAndPop(工作和放大器; poppedValue)
    {
      提高::互斥:: scoped_lock的锁(_mutex);
      而(_queue.empty())
      {
        _conditionVariable.wait(锁);
      }      poppedValue = _queue.front();
      _queue.pop();
    }};///线程池张贴工作木卫一服务
一流的线程池
{
  上市 :
    线程池(中间体noOfThreads = 1);
    〜线程池();    模板&LT;一流的FUNC&GT;
      无效后(FUNC F);    提高:: ASIO :: io_service对象和放大器; getIoService();  私人的 :
    提高:: ASIO :: io_service对象_ioService;
    提高:: ASIO :: io_service对象::工作_work;
    提高:: thread_group _threads;
};  内嵌线程池::线程池(INT noOfThreads)
:_work(_ioService)
{
  的for(int i = 0; I&LT; noOfThreads ++我)// 4
    _threads.create_thread(升压::绑定(安培;提高:: ASIO :: io_service对象::来看,&安培; _ioService));
}内嵌线程池::〜线程池()
{
  _ioService.stop();
  _threads.join_all();
}内嵌的boost ::支持ASIO :: io_service对象和放大器;线程池:: getIoService()
{
  返回_ioService;
}  模板&LT;一流的FUNC&GT;
无效线程池::后(FUNC F)
{
  _ioService.post(F);
}
模板&LT; typename的T&GT;
一流的管理;///工人做了一些工作。
模板&LT; typename的T&GT;
类工人{    Ť_data;
    INT _taskList;
    提高::互斥_mutex;
    经理&LT; T&GT; * _hndl;  上市:    工人(T数据,诠释任务,经理&LT; T&GT; * hndle):
    _data(数据),
    _taskList(任务)
    _hndl(hndle)
    {
    }    BOOL作业()
    {
      提高::互斥:: scoped_lock的锁(_mutex);
      性病::法院LT&;&LT;......男子在工作......&LT;&LT; ++ _数据&LT;&LT;的std :: ENDL;
       - _任务列表;
      如果(taskDone())
       _hndl-&GT;结束();
    }    布尔taskDone()
    {
      性病::法院LT&;&LT;任务&LT;&LT; _taskList&LT;&LT;的std :: ENDL&LT;&LT;的std :: ENDL;
      如果(_taskList == 0)
      {
        性病::法院LT&;&LT;任务完成&LT;&LT;的std :: ENDL;
        返回true;
      }
      否则返回false;
    }};///作业处理器将等待新的就业机会和
///执行它们在使用线程池接收到一个新工作。
//一旦所有工作完成hndler退出。
模板&LT; typename的T&GT;
类经理{ 上市:   TYPEDEF的boost ::功能&LT;布尔(工人&LT; T&GT; *)&GT; FUNC;   经理(INT THREADCOUNT):
   _threadCount(经纬)
   _isWorkCompleted(假)
   {
     _pool =新的线程池(_threadCount);     提高::线程jobRunner(安培;管理::执行,这一点);
   }   无效添加(Func键楼工作者LT; T&GT; *实例)
   {
     工作职位(例如,F);
     _jobQueue.push(工作);
   }   无效结束()
   {
     提高::互斥:: scoped_lock的锁(_mutex);
     _isWorkCompleted = TRUE;
     //发送一个虚拟工作
     添加(NULL,NULL);
   }   无效workComplete()
   {
     性病::法院LT&;&LT;工作做得很好。&LT;&LT;的std :: ENDL;
   }   布尔isWorkDone()
   {
     提高::互斥:: scoped_lock的锁(_mutex);
     如果(_isWorkCompleted)
       返回true;
     返回false;
   }   无效的execute()
   {
      招聘工作;     而(!isWorkDone())
     {
       _jobQueue.waitAndPop(工作);        FUNC F =提振::获得&LT; 1 GT;(工作);
        工人&LT; T&GT; * PTR =的boost ::获得℃的&GT;(工作);        如果(F)
        {
          _pool-&GT;后期(的boost ::绑定(F,PTR));
        }
        其他
          打破;
     }     性病::法院LT&;&LT;完整&LT;&LT;的std :: ENDL;
   }
 私人的:  线程池* _pool;
  INT _threadCount;
  TYPEDEF提振::元组LT;工作者LT; T&GT; *,Func键&GT;工作;
  JobQueue&LT;人才与GT; _jobQueue;
  布尔_isWorkCompleted;
  提高::互斥_mutex;
};TYPEDEF的boost ::功能&LT;布尔(工人&LT; INT&GT; *)&GT; IntFunc;
TYPEDEF的boost ::功能&LT;布尔(工人&LT;焦炭&GT; *)&GT; CharFunc;
诠释的main()
{
  提高:: ASIO :: io_service对象IOService的;  经理&LT;&诠释GT; jobHndl(2);
  工人&LT;&诠释GT; wrk1(0,4,&安培; jobHndl);  IntFunc F =&放大器;工作者LT; INT&GT; ::工作;  jobHndl.add(F,放大器; wrk1);
  jobHndl.add(F,放大器; wrk1);
  jobHndl.add(F,放大器; wrk1);
  jobHndl.add(F,放大器; wrk1);  经理&LT;焦炭&GT; jobHndl2(2);
  工人&LT;焦炭&GT; wrk2(0,'一个',&放大器; jobHndl2);  CharFunc F2 =&放大器;工作者LT;焦炭&GT; ::工作;  jobHndl2.add(F2,&放大器; wrk2);
  jobHndl2.add(F2,&放大器; wrk2);
  jobHndl2.add(F2,&放大器; wrk2);
  jobHndl2.add(F2,&放大器; wrk2);  ioService.run();
  而(1){}
  返回0;
}

I found a good implementation of boost based thread pool which is an improvement over this and this . it is very easy to understand and test. It looks like this:

#include <boost/thread/thread.hpp>
#include <boost/asio.hpp>
// the actual thread pool
struct ThreadPool {
   ThreadPool(std::size_t);
   template<class F>
   void enqueue(F f);
   ~ThreadPool();    

   // the io_service we are wrapping
   boost::asio::io_service io_service;
   // dont let io_service stop
   boost::shared_ptr<boost::asio::io_service::work> work;
   //the threads
   boost::thread_group threads;
};

// the constructor just launches some amount of workers
ThreadPool::ThreadPool(size_t nThreads)
   :io_service()
   ,work(new boost::asio::io_service::work(io_service))
{
   for ( std::size_t i = 0; i < nThreads; ++i ) {
    threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
   }
}

// add new work item to the pool
template<class F>
void ThreadPool::enqueue(F f) {
   io_service.post(f);
}

// the destructor joins all threads
ThreadPool::~ThreadPool() {
work.reset();
io_service.run();
}

//tester: 
void f(int i)
{
    std::cout << "hello " << i << std::endl;
    boost::this_thread::sleep(boost::posix_time::milliseconds(300));
    std::cout << "world " << i << std::endl;
}

//it can be tested via:

int main() {
   // create a thread pool of 4 worker threads
   ThreadPool pool(4);

   // queue a bunch of "work items"
   for( int i = 0; i < 8; ++i ) {
      std::cout << "task " << i << " created" << std::endl;
      pool.enqueue(boost::bind(&f,i));
   }
}

g++ ThreadPool-4.cpp -lboost_system -lboost_thread

Now the question: I need to know how I can modify the implementation to be able to use this thread pool batch by batch- only when the first set of my work is fully completed by the thread pool, I need to supply the second set and so on. I tried to play with .run() and .reset() (found in the destructor) between the batch jobs but no luck:

//adding methods to the tread pool :
//reset the asio work and thread
void ThreadPool::reset(size_t nThreads){

work.reset(new boost::asio::io_service::work(io_service));
   for ( std::size_t i = 0; i < nThreads; ++i ) {
    threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
   }
    std::cout << "group size : " << threads.size() << std::endl;
}

//join, and even , interrupt
void ThreadPool::joinAll(){   
  threads.join_all();
  threads.interrupt_all();
}

//tester
int main() {
   // create a thread pool of 4 worker threads
   ThreadPool pool(4);

   // queue a bunch of "work items"
   for( int i = 0; i < 20; ++i ) {
      std::cout << "task " << i << " created" << std::endl;
          pool.enqueue(boost::bind(&f,i));
   }
   //here i play with the asio work , io_service and and the thread group
   pool.work.reset();
   pool.io_service.run();
   std::cout << "after run" << std::endl; 
   pool.joinAll();
   std::cout << "after join all" << std::endl; 
   pool.reset(4);
   std::cout << "new thread group size: " << pool.threads.size() << std::endl;///btw: new threa group size is 8. I expected 4! 
    // second batch... never completes
   for( int i = 20; i < 30; ++i ) {
          pool.enqueue(boost::bind(&f,i));
   }
}

The second batch doesn't complete. I will appreciate if you help me fix this. thank you

UPDATE- Solution:

based on a solution by Nik, I developed a solution using condition variable. Just add the following code to the original class:

// add new work item to the pool
template<class F>
void ThreadPool::enqueue(F f) {
    {
        boost::unique_lock<boost::mutex> lock(mutex_);
        nTasks ++;
    }
    //forwarding the job to wrapper()
    void (ThreadPool::*ff)(boost::tuple<F>) = &ThreadPool::wrapper<F>;
    io_service.post(boost::bind(ff, this, boost::make_tuple(f))); //using a tuple seems to be the only practical way. it is mentioned in boost examples.
}
//run+notfiy
template<class F>
void ThreadPool::wrapper(boost::tuple<F> f) {
    boost::get<0>(f)();//this is the task (function and its argument) that has to be executed by a thread
    {
        boost::unique_lock<boost::mutex> lock(mutex_);
        nTasks --;
        cond.notify_one();
    }
}

void ThreadPool::wait(){
    boost::unique_lock<boost::mutex> lock(mutex_);
    while(nTasks){
        cond.wait(lock);
    }
}

Now you may call wait() method between batches of work. one problem however: Even after the last batch, I have to call pool.wait() because the thread pool's scope will end after that and thread pool's destructor will be invoked. During destruction, some of the jobs are done and it will be the time to call the .notify(). As the Threadpool::mutex during destruction is invalidated, exceptions occur during locking. your suggestion will be appreciated.

解决方案

A condition variable could be used to achieve desired result.

Implement a function responsible for calling enqueue the tasks and wait on a condition variable. Condition variable is notified when all tasks assigned to the pool are complete.

Every thread checks if the jobs are complete or not. Once all the jobs are complete condition variable is notified.

//An example of what you could try, this just an hint for what could be explored.

     void jobScheduler()
    {
      int jobs = numberOfJobs; //this could vary and can be made shared memory

       // queue a bunch of "work items"
       for( int i = 0; i < jobs; ++i ) 
       {
          std::cout << "task " << i << " created" << std::endl;
          pool.enqueue(boost::bind(&f,i));
       }
       //wait on a condition variable
      boost::mutex::scoped_lock lock(the_mutex);
      conditionVariable.wait(lock); //Have this varibale notified from any thread which realizes that all jobs are complete.
     }


Solution 2

I have a new working solution, with some assumption about syntax of functions being called back, but that could be changed as per requirement.

Continuing on the lines of above I use condition variable for managing my tasks but with a difference.

  1. Create a queue of jobs.
  2. A Manager which waits for new JOBS in the queue.
  3. Once a job is received a notification is sent to waiting manager about the same.
  4. Worker maintains a handle to Manager. When all the tasks assigned are complete Manger is informed.
  5. Manager on getting a call for end, stops waiting for new JOBS in queue and exits.


#include <iostream>
#include <queue>
#include <boost/thread/thread.hpp>
#include <boost/asio.hpp>
#include <boost/tuple/tuple.hpp> 
#include <boost/tuple/tuple_io.hpp> 
#include <boost/function.hpp> 

///JOB Queue hold all jobs required to be executed
template<typename Job>
class JobQueue
{
  private:

    std::queue<Job> _queue;
    mutable boost::mutex _mutex;
    boost::condition_variable _conditionVariable;

  public:
    void push(Job const& job)
    {
      boost::mutex::scoped_lock lock(_mutex);
      _queue.push(job);
      lock.unlock();
      _conditionVariable.notify_one();
    }

    bool empty() const
    {
      boost::mutex::scoped_lock lock(_mutex);
      return _queue.empty();
    }

    bool tryPop(Job& poppedValue)
    {
      boost::mutex::scoped_lock lock(_mutex);
      if(_queue.empty())
      {
        return false;
      }

      poppedValue = _queue.front();
      _queue.pop();
      return true;
    }

    void waitAndPop(Job& poppedValue)
    {
      boost::mutex::scoped_lock lock(_mutex);
      while(_queue.empty())
      {
        _conditionVariable.wait(lock);
      }

      poppedValue = _queue.front();
      _queue.pop();
    }

};

///Thread pool for posting jobs to io service
class ThreadPool
{
  public :
    ThreadPool( int noOfThreads = 1) ;
    ~ThreadPool() ;

    template< class func >
      void post( func f ) ;

    boost::asio::io_service &getIoService() ;

  private :
    boost::asio::io_service _ioService;
    boost::asio::io_service::work _work ;
    boost::thread_group _threads;
};

  inline ThreadPool::ThreadPool( int noOfThreads )
: _work( _ioService )
{
  for(int i = 0; i < noOfThreads ; ++i) // 4
    _threads.create_thread(boost::bind(&boost::asio::io_service::run, &_ioService));
}

inline ThreadPool::~ThreadPool()
{
  _ioService.stop() ;
  _threads.join_all() ;
}

inline boost::asio::io_service &ThreadPool::getIoService()
{
  return _ioService ;
}

  template< class func >
void ThreadPool::post( func f )
{
  _ioService.post( f ) ;
}


template<typename T>
class Manager;

///Worker doing some work.
template<typename T>
class Worker{

    T _data;
    int _taskList;
    boost::mutex _mutex;
    Manager<T>* _hndl;

  public:

    Worker(T data, int task, Manager<T>* hndle):
    _data(data),
    _taskList(task),
    _hndl(hndle)
    {
    }

    bool job()
    {
      boost::mutex::scoped_lock lock(_mutex);
      std::cout<<"...Men at work..."<<++_data<<std::endl;
      --_taskList;
      if(taskDone())
       _hndl->end();
    } 

    bool taskDone()
    {
      std::cout<<"Tasks  "<<_taskList<<std::endl<<std::endl;
      if(_taskList == 0)
      {
        std::cout<<"Tasks done "<<std::endl;
        return true;
      }
      else false;
    }

};

///Job handler waits for new jobs and
///execute them as when a new job is received using Thread Pool.
//Once all jobs are done hndler exits.
template<typename T>
class Manager{

 public:

   typedef boost::function< bool (Worker<T>*)> Func;

   Manager(int threadCount):
   _threadCount(threadCount),
   _isWorkCompleted(false)
   {
     _pool = new ThreadPool(_threadCount);

     boost::thread jobRunner(&Manager::execute, this);
   }

   void add(Func f, Worker<T>* instance)
   {
     Job job(instance, f);
     _jobQueue.push(job);
   }

   void end()
   {
     boost::mutex::scoped_lock lock(_mutex);
     _isWorkCompleted = true;
     //send a dummy job
     add( NULL, NULL);
   }

   void workComplete()
   {
     std::cout<<"Job well done."<<std::endl;
   }

   bool isWorkDone()
   {
     boost::mutex::scoped_lock lock(_mutex);
     if(_isWorkCompleted)
       return true;
     return false;
   }

   void execute()
   {
      Job job;

     while(!isWorkDone())
     {
       _jobQueue.waitAndPop(job);

        Func f  = boost::get<1>(job);
        Worker<T>* ptr = boost::get<0>(job);

        if(f)
        {
          _pool->post(boost::bind(f, ptr));
        }
        else
          break;
     }

     std::cout<<"Complete"<<std::endl;
   }


 private:

  ThreadPool *_pool;
  int _threadCount;
  typedef boost::tuple<Worker<T>*, Func > Job;
  JobQueue<Job> _jobQueue;
  bool _isWorkCompleted;
  boost::mutex _mutex;
};

typedef boost::function< bool (Worker<int>*)> IntFunc;
typedef boost::function< bool (Worker<char>*)> CharFunc;


int main()
{
  boost::asio::io_service ioService;

  Manager<int> jobHndl(2);
  Worker<int> wrk1(0,4, &jobHndl);

  IntFunc f= &Worker<int>::job;

  jobHndl.add(f, &wrk1);
  jobHndl.add(f, &wrk1);
  jobHndl.add(f, &wrk1);
  jobHndl.add(f, &wrk1);

  Manager<char> jobHndl2(2);
  Worker<char> wrk2(0,'a', &jobHndl2);

  CharFunc f2= &Worker<char>::job;

  jobHndl2.add(f2, &wrk2);
  jobHndl2.add(f2, &wrk2);
  jobHndl2.add(f2, &wrk2);
  jobHndl2.add(f2, &wrk2);

  ioService.run();
  while(1){}
  return 0;
}

这篇关于如何使用批次相同的线程池批的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆