Boost::asio范例分析 服务端线程池实现

  在http范例的server2实现中引入了线程池,server2的业务逻辑实现与server1相似.这里只分析与线程池有关的代码.
  main函数中添加了一个额外的参数指定线程池大小.并在server类中声明了一个线程池类成员io_service_pool io_service_pool_;这个类的构造函数接收一个整型参数io_service_pool_size指定线程池大小.在server类中创建connection实例时需要从线程池中获取io_service对象,这是使用线程池类的io_service_pool_.get_io_service()成员函数实现的,根据asio的约定,异步操作由哪个线程执行与其相关io_service对象有关,调用io_service::run()成员函数的线程才能执行相关异步操作.因此要想实现线程池,只需要在线程池对象中创建多个io_service对象,并创建同样多的线程对象,在每个线程中都调用一个io_service对象的run()方法.这样通过在线程池中均匀的获取io_service对象,就可以实现将异步操作均匀的分配给多个线程来执行了.
  先看看server类创建connection的代码:
void server::start_accept()
{
  new_connection_.reset(new connection(
        io_service_pool_.get_io_service(), request_handler_));
  acceptor_.async_accept(new_connection_->socket(),
      boost::bind(&server::handle_accept, this,
        boost::asio::placeholders::error));
}
  connection构造函数需要一个io_service对象,这里是从线程池中获取的,同时也就指定了这个connection类中的异步操作都由线程池中相应的线程来处理.
  下面重点分析一下线程池类的定义和实现.io_service_pool从noncopyable继承,不能进行拷贝复制.
  io_service_pool定义的数据成员:
    std::vector io_services_;//存放io_service对象的容器.
    std::vector work_;             //存放工作者对象的容器
    std::size_t next_io_service_;            //指定下一个将被分配的io_service
  io_service_pool定义的函数成员:
    显式构造函数:初始化next_io_service_为0,创建指定线程池大小个数的io_service对象和工作者对象,并分别存放在io_service_容器和work_容器中.
  for (std::size_t i = 0; i < pool_size; ++i)//创建多个io_service和多个工作者对象
  {
    io_service_ptr io_service(new boost::asio::io_service);
    work_ptr work(new boost::asio::io_service::work(*io_service));
    io_services_.push_back(io_service);
    work_.push_back(work);
  }
    run函数:根据指定线程池大小创建多个线程,这些线程的执行函数为相应io_service对象的run方法.并让主线程阻塞等待所有线程执行完毕.
  for (std::size_t i = 0; i < io_services_.size(); ++i)
  {
    boost::shared_ptr thread(new boost::thread(
          boost::bind(&boost::asio::io_service::run, io_services_[i])));
    threads.push_back(thread);
  }
  //主线程一直阻塞等待 直到所有线程结束
  for (std::size_t i = 0; i < threads.size(); ++i)
    threads[i]->join();
    stop函数:调用所有io_service对象的stop方法,停止处理异步通信.
    get_io_service函数:这个函数根据next_io_service_数据成员获取在容器中一个io_service对象,并将next_io_service_加1,如果达到容器的最大个数,则置为0.实现循环获取io_service对象的目的.
boost::asio::io_service& io_service_pool::get_io_service()
{
  //循环获取io_service对象 异步操作由创建io_service的线程执行,从而实现为线程池中的线程均匀分配任务
  boost::asio::io_service& io_service = *io_services_[next_io_service_];
  ++next_io_service_;
  if (next_io_service_ == io_services_.size())
    next_io_service_ = 0;
  return io_service;
}

最后注意存放在容器中的线程,io_service对象,工作者对象,线程对象都是使用shared_ptr指针保护的,保证了这些对象的自动释放.

这里创建了多个io_service对象,也可以只创建一个io_service对象,多个线程都执行io_service::run()函数,则异步操作可在这里线程中进行随机分配.请看server3范例.

你可能感兴趣的:(C/C++,C++与QT)