任务队列的模式

  单线程单任务队列方式

  任务队列已经提供了run接口,绑定任务队列的线程只需执行此函数即可,此函数除非用户显示的调用任务队列的close接口,否则run函数永不返回。任务队列的close接口是专门用来停止任务队列的工作的,代码如下:

void close()
    {
        lock_guard_t lock(m_mutex);
        m_flag = false;
        m_cond.broadcast();
}

  首先设置了关闭标记,然后在条件变量上执行broadcast, 任务队列的run函数也会由此退出。在回头看一下run接口的代码你会发现,检查任务队列是否关闭(m_flag 变量)的代码是在任务队列为空的时候才检测的,这样能够保证任务队列被全部执行后,run函数才返回。

  下面是一个使用任务队列的helloworld的示例:

class foo_t
{
public:
    void print(int data)
    {
        cout << "helloworld, data:" <<data << " thread id:"<< ::pthread_self() << endl;
    }
    void print_callback(int data, void (*callback_)(int))
    {
        callback_(data);
    }
    static void check(int data)
    {
        cout << "helloworld, data:" <<data << " thread id:"<< ::pthread_self() << endl;
    }
};

//  单线程单任务队列
void test_1()
{
    thread_t thread;
    task_queue_t tq;

    thread.create_thread(task_binder_t::gen(&task_queue_t::run, &tq), 1);

    foo_t foo;
    for (int i = 0; i < 100; ++i)
    {
        cout << "helloworld, thread id:"<< ::pthread_self() << endl;
        tq.produce(task_binder_t::gen(&foo_t::print, &foo, i));
        sleep(1);
    }
    thread.join();
}
int main(int argc, char* argv[])
{
    test_1();
    return 0;
}

  本例使用单线程单任务队列的方式,由于只有一个线程绑定在任务队列上,所以任务的执行会严格按照先入先出的方式执行。优点是能够保证逻辑操作的有序性,所以为常用。

  多线程多任务队列方式

  如果想利用更多线程,那么创建更多线程的同时,仍然保证每个任务队列绑定在单线程上。让不同的任务队列并行执行可以了。

  下面几种情况适用此模式:

  ● 比如网游中数据库一般会创建连接池,用户的操作数据库都是有数据库线程池完成,在将结果投递给逻辑层。对每个用户的数据增删改查操作都必须是有序的,所以每个用户绑定一个固定的任务队列。而不同的用户的数据修改互不干扰,不同的用户分配不同的任务队列即可。

  ● 比如网络层中的多个socket的读写是互不干扰的,可以创建两个或更多线程,每个对应一个任务队列,不同的socket的操作可以随机的分配一个任务队列(注意分配是随机的,一旦分配了,单个socket的所有操作都会由这个任务队列完成,保证逻辑有序性)。