5_04_GLib库入门与实践_线程池

简介

线程池是在多线程编程时经常用到的技术。在进行多线程任务处理时,如果线程频繁创建和销毁,将会使系统开销变大,在这种情况下,上一个任务执行完后不销毁之前创建的线程,后续任务重用该线程,将会大大减小开销。为了管理这些创建之后不再销毁的线程,便有了线程池的概念。
GLib的线程池除了提供一般的线程池函数外,还提供了诸如获取当前运行的线程数量、获取未处理的任务数量、获取或设置线程池的最大线程数量、获取未使用的线程数量、设置未使用的最大线程数量、停止所有目前未使用的线程,但经过实际测试,这里面有些功能并未生效。

数据结构

线程池有三个成员变量。
struct GThreadPool {
GFunc func;
gpointer user_data;
gboolean exclusive;
};

函数列表

GThreadPool * 	g_thread_pool_new ()
gboolean 	g_thread_pool_push ()
gboolean 	g_thread_pool_set_max_threads ()
gint 	g_thread_pool_get_max_threads ()
guint 	g_thread_pool_get_num_threads ()
guint 	g_thread_pool_unprocessed ()
void 	g_thread_pool_free ()
void 	g_thread_pool_set_max_unused_threads ()
gint 	g_thread_pool_get_max_unused_threads ()
guint 	g_thread_pool_get_num_unused_threads ()
void 	g_thread_pool_stop_unused_threads ()
void 	g_thread_pool_set_sort_function ()
void 	g_thread_pool_set_max_idle_time ()
guint 	g_thread_pool_get_max_idle_time ()
gboolean 	g_thread_pool_move_to_front ()

函数功能分类

创建

GThreadPool * 	g_thread_pool_new ()

销毁

void 	g_thread_pool_free ()

发送数据

gboolean 	g_thread_pool_push ()

查询

// 获取线程池的最大线程个数
gint 	g_thread_pool_get_max_threads ()

// (不可用)获取线程池中正在运行的线程个数(注:经测试,此值与线程池的最大线程个数相同,貌似没有生效)
guint 	g_thread_pool_get_num_threads ()

// (不可用)获取线程池最大不可用线程数量,作用未知,此接口的值所有GThreadPool线程池共用
gint 	g_thread_pool_get_max_unused_threads ()

// (不可用)线程处理完本任务要处理下一个任务前的暂停时间,经测试也不生效
guint 	g_thread_pool_get_max_idle_time ()

//返回线程池中还没有处理的任务队列中的任务个数
guint 	g_thread_pool_unprocessed ()

设置

// 设置线程池的最大线程个数
// 如果线程池是独占的(g_thread_pool_new的exclusive参数为TRUE),则不允许设置为-1
// 如果线程池是非独占的,此值设置为-1表明线程池最大线程个数不限制。
// 如果此值设置为0,则线程池停止工作,直到其再次被设置为一个非0值,线程池重新工作。
gboolean 	g_thread_pool_set_max_threads ()

// (不可用)设置最大不可用线程数量,默认值为2
void 	g_thread_pool_set_max_unused_threads ()

// (不可用)设置处理完本任务要处理下一个任务前的暂停时间,经测试可以设置成功,但并不生效
void 	g_thread_pool_set_max_idle_time ()

任务优先执行

// 将一个线程提到线程执行队列的最前面,使其比其他线程更快被执行到
gboolean 	g_thread_pool_move_to_front ()

任务排序

void 	g_thread_pool_set_sort_function ()

其他

// 停止未被使用的线程
void 	g_thread_pool_stop_unused_threads ()

函数功能说明及综合演示

向线程池发送任务

创建一个线程池,并通过g_thread_pool_push函数向线程池发送任务,使其执行。
示例代码如下:
源码见glib_examples\glib_threadpool\glib_threadpool_push

#include <glib.h>

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("get data: %d \n", GPOINTER_TO_INT(data));
}

void test_thread_pool_push(void)
{
    GThreadPool *pool = NULL;
    GError *error = NULL;
    gint max_threads = 4;

    pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, FALSE, &error);

    g_thread_pool_push(pool, GINT_TO_POINTER(99), &error);
    g_usleep(100*1000);

    g_thread_pool_free(pool, TRUE, TRUE);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool_push();
}

运行结果:

[root@centos7_6 build]#glib_threadpool_push
get data: 99

下面程序演示将g_thread_pool_push函数放到独立的线程中。
源码见glib_examples\glib_threadpool\glib_theadpool_push2

#include <glib.h>
#include <pthread.h>

#define TEST_THREAD_POOL_FIN 9999

GThreadPool *g_pool = NULL;

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("tid %ld: get data: %d \n", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free \n");
        g_thread_pool_free(g_pool, TRUE, TRUE);
    }
}

gpointer test_thread_func(gpointer data)
{
    GThreadPool *pool = (GThreadPool *)data;
    g_thread_pool_push(pool, GINT_TO_POINTER(99), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(100), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(101), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(102), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(103), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(TEST_THREAD_POOL_FIN), NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 4;

    GThread *thd = NULL;

    g_pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, g_pool);
    g_usleep(500*1000);
    g_thread_join(thd);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

运行结果:

[root@centos7_6 build]# ./glib_theadpool_push2 
tid 140058740213504: get data: 99 
tid 140058756998912: get data: 100 
tid 140058615084800: get data: 101 
tid 140058748606208: get data: 102 
tid 140058740213504: get data: 103 
tid 140058756998912: get data: 9999 
theadpool free
不同线程执行不同的函数

在一些场景下,希望g_thread_pool_push函数向线程池发送的数据,可以被不同的线程执行函数所执行。
下面就演示这一功能。
先来看一个错误的例子。
源码见glib_examples\glib_threadpool\glib_theadpool_diff_func_err

#include <glib.h>
#include <pthread.h>

typedef int (*foobar_method)(gint a, gint b);

typedef struct foobar_tag {
    gint foo;
    gint bar;
    foobar_method func; 
}foobar_t;

static gint test_foobar_add(gint a, gint b)
{
    return a + b;
}

static gint test_foobar_multi(gint a, gint b)
{
    return a * b;
}

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    gint ret_val = 0;
    foobar_t *foobar = NULL;

    foobar = g_new0(foobar_t, 1);
    if(NULL == foobar) {
        return;
    }

    foobar->foo = ((foobar_t *)(data))->foo;
    foobar->bar = ((foobar_t *)(data))->bar;
    foobar->func = ((foobar_t *)(data))->func;

    ret_val = foobar->func(foobar->foo, foobar->bar);
    g_print("ret_val: %d \n", ret_val);

    g_free(foobar);
}

gpointer test_thread_func(gpointer data)
{
    foobar_t *foobar = NULL;
    GThreadPool *pool = (GThreadPool *)data;

    foobar = g_new0(foobar_t, 1);
    foobar->foo = 2;
    foobar->bar = 3;
    foobar->func = test_foobar_add;
    g_thread_pool_push(pool, foobar, NULL);

    foobar->foo = 2;
    foobar->bar = 3;
    foobar->func = test_foobar_multi;
    g_thread_pool_push(pool, foobar, NULL);

    g_free(foobar);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 4;
    GThreadPool *pool = NULL;
    GThread *thd = NULL;

    pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, pool);
    g_usleep(100*1000);
    g_thread_join(thd);

    g_thread_pool_free(pool, TRUE, TRUE);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

运行结果:

[root@centos7_6 build]# ./glib_theadpool_diff_func_err 
ret_val: 5 
ret_val: 6 
[root@centos7_6 build]# ./glib_theadpool_diff_func_err 
ret_val: 0 
ret_val: 0 
[root@centos7_6 build]# ./glib_theadpool_diff_func_err 
ret_val: 5 
段错误 (核心已转储)
[root@centos7_6 build]# ./glib_theadpool_diff_func_err 
ret_val: 0 
ret_val: 0 
[root@centos7_6 build]# ./glib_theadpool_diff_func_err 
ret_val: 6 
ret_val: 6

原因出在test_thread_func函数。
本函数可能导致两个问题:
1.两次push完之后,test_thread_func内的foobar被释放,此时线程池的执行函数test_thread_pool_func才刚开始执行,foobar->func地址变为未知,运行结果也未知。
2.第一次push完之后,线程池的一个线程被唤起,test_thread_pool_func开始执行,foobar->func此时为test_foobar_add,运行之后得到的值为5,第二次push完后,线程池还没开始运行,
test_thread_func内的foobar被释放,此时线程池的执行函数test_thread_pool_func才开始执行,foobar->func地址变为未知,导致段错误。

下面是正确的例子。
源码见glib_examples\glib_threadpool\glib_theadpool_diff_func

#include <glib.h>
#include <pthread.h>

typedef int (*foobar_method)(gint a, gint b);

typedef struct foobar_tag {
    gint foo;
    gint bar;
    foobar_method func; 
}foobar_t;

static gint test_foobar_add(gint a, gint b)
{
    return a + b;
}

static gint test_foobar_multi(gint a, gint b)
{
    return a * b;
}

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    gint ret_val = 0;
    foobar_t *foobar = NULL;

    foobar = (foobar_t *)data;
    if(NULL == foobar) {
        g_print("input param is NULL \n");
        return;
    }

    ret_val = foobar->func(foobar->foo, foobar->bar);
    g_print("ret_val: %d \n", ret_val);

    g_free(foobar);
}

gpointer test_thread_func(gpointer data)
{
    foobar_t *foobar1 = NULL;
    foobar_t *foobar2 = NULL;
    GThreadPool *pool = (GThreadPool *)data;

    foobar1 = g_new0(foobar_t, 1);
    foobar1->foo = 2;
    foobar1->bar = 3;
    foobar1->func = test_foobar_add;
    g_thread_pool_push(pool, foobar1, NULL);

    foobar2 = g_new0(foobar_t, 1);
    foobar2->foo = 2;
    foobar2->bar = 3;
    foobar2->func = test_foobar_multi;
    g_thread_pool_push(pool, foobar2, NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 4;
    GThreadPool *pool = NULL;
    GThread *thd = NULL;

    pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, pool);
    g_usleep(100*1000);
    g_thread_join(thd);

    g_thread_pool_free(pool, TRUE, TRUE);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

多次运行结果:

[root@centos7_6 build]# ./glib_theadpool_diff_func
ret_val: 5 
ret_val: 6 
[root@centos7_6 build]# ./glib_theadpool_diff_func
ret_val: 6 
ret_val: 5 
[root@centos7_6 build]# ./glib_theadpool_diff_func
ret_val: 5 
ret_val: 6
设置最大线程数

g_thread_pool_set_max_threads函数可以设置线程池最大线程个数。
下面是演示程序。
源码见glib_examples\glib_threadpool\glib_theadpool_set_max_threads

#include <glib.h>
#include <pthread.h>

#define TEST_THREAD_POOL_FIN 9999

GThreadPool *g_pool = NULL;

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("tid %ld: get data: %d \n", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free \n");
        g_thread_pool_free(g_pool, TRUE, TRUE);
    }
}

gpointer test_thread_func(gpointer data)
{
    GThreadPool *pool = (GThreadPool *)data;
    g_thread_pool_push(pool, GINT_TO_POINTER(99), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(100), NULL);
    g_usleep(20*1000); //sleep 20ms to process 99 and 100
    g_thread_pool_set_max_threads(pool, 0, NULL);
    g_print("set max threads to 0, sleep 1s and set max to 4 \n");
    g_usleep(1*1000*1000);
    g_thread_pool_set_max_threads(pool, 4, NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(101), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(102), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(103), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(104), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(105), NULL);

    g_usleep(60*1000);
    g_print("unprocessed: %d \n", g_thread_pool_unprocessed(pool));
    g_print("max threads: %d \n", g_thread_pool_get_max_threads(pool));
    g_print("num threads: %d \n", g_thread_pool_get_num_threads(pool));
    g_print("num unused threads: %d \n", g_thread_pool_get_num_unused_threads());
    g_print("max unused threads: %d \n", g_thread_pool_get_max_unused_threads());
    
    g_thread_pool_push(pool, GINT_TO_POINTER(TEST_THREAD_POOL_FIN), NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 3;

    GThread *thd = NULL;

    g_pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, g_pool);
    g_usleep(500*1000);
    g_thread_join(thd);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

运行结果:

[root@centos7_6 build]# ./glib_theadpool_set_max_threads
tid 140312679347968: get data: 99 
tid 140312670955264: get data: 100 
set max threads to 0, sleep 1s and set max to 4 
tid 140312670955264: get data: 101 
tid 140312654169856: get data: 102 
tid 140312687740672: get data: 103 
tid 140312679347968: get data: 104 
tid 140312654169856: get data: 105 
unprocessed: 0 
max threads: 4 
num threads: 4 
num unused threads: 0 
max unused threads: 2 
tid 140312670955264: get data: 9999
对线程中的任务排序

g_thread_pool_set_sort_function可以对线程中的任务自定义排序。
下面是演示程序:
源码见glib_examples\glib_threadpool\glib_theadpool_set_sort_function

#include <glib.h>
#include <pthread.h>

#define TEST_THREAD_POOL_FIN 9999

GThreadPool *g_pool = NULL;

gint _test_thread_int_cmp_func(gconstpointer a, gconstpointer b, gpointer user_data)
{
    return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("tid %ld: get data: %d \n", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free \n");
        g_thread_pool_free(g_pool, TRUE, TRUE);
    }
}

gpointer test_thread_func(gpointer data)
{
    GThreadPool *pool = (GThreadPool *)data;

    g_thread_pool_set_max_threads(pool, 0, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(99), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(120), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(101), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(106), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(203), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(104), NULL);

    g_thread_pool_set_sort_function(pool, _test_thread_int_cmp_func, NULL);
    g_thread_pool_set_max_threads(pool, 1, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(TEST_THREAD_POOL_FIN), NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 1;

    GThread *thd = NULL;

    g_pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, g_pool);
    g_usleep(500*1000);
    g_thread_join(thd);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

运行结果:

[root@centos7_6 build]# ./glib_theadpool_set_sort_function
tid 139765831759616: get data: 99 
tid 139765831759616: get data: 101 
tid 139765831759616: get data: 104 
tid 139765831759616: get data: 106 
tid 139765831759616: get data: 120 
tid 139765831759616: get data: 203 
tid 139765831759616: get data: 9999 
theadpool free

上述例子创建了最大个数为1的线程池,如果创建的最大个数为2呢?
下面是演示程序:
源码见glib_examples\glib_threadpool\glib_theadpool_set_sort_function_2_threads

#include <glib.h>
#include <pthread.h>

#define TEST_THREAD_POOL_FIN 9999

GThreadPool *g_pool = NULL;

gint _test_thread_int_cmp_func(gconstpointer a, gconstpointer b, gpointer user_data)
{
    return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("tid %ld: get data: %d \n", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free \n");
        g_thread_pool_free(g_pool, TRUE, TRUE);
    }
}

gpointer test_thread_func(gpointer data)
{
    GThreadPool *pool = (GThreadPool *)data;

    g_thread_pool_set_max_threads(pool, 0, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(99), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(120), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(101), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(106), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(203), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(104), NULL);

    g_thread_pool_set_sort_function(pool, _test_thread_int_cmp_func, NULL);
    g_thread_pool_set_max_threads(pool, 1, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(TEST_THREAD_POOL_FIN), NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 2; //set initial max threads to 2

    GThread *thd = NULL;

    g_pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, g_pool);
    g_usleep(500*1000);
    g_thread_join(thd);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

运行结果:

[root@centos7_6 build]# ./glib_theadpool_set_sort_function_2_threads
tid 140527418357504: get data: 99 
tid 140527409964800: get data: 120 
tid 140527418357504: get data: 101 
tid 140527418357504: get data: 104 
tid 140527418357504: get data: 106 
tid 140527418357504: get data: 203 
tid 140527418357504: get data: 9999 
theadpool free

可以看到有两个tid,说明线程池创建时已经有线程在运行了,即使设置了g_thread_pool_set_max_threads为0,重新设置为非0时,之前创建的线程会继续运行。

如果在线程池创建时初始化指定最大线程数是4呢?
下面是演示程序:
源码见glib_examples\glib_threadpool\glib_theadpool_set_sort_function_4_threads

#include <glib.h>
#include <pthread.h>

#define TEST_THREAD_POOL_FIN 9999

GThreadPool *g_pool = NULL;

gint _test_thread_int_cmp_func(gconstpointer a, gconstpointer b, gpointer user_data)
{
    return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("tid %ld: get data: %d \n", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free \n");
        g_thread_pool_free(g_pool, TRUE, TRUE);
    }
}

gpointer test_thread_func(gpointer data)
{
    GThreadPool *pool = (GThreadPool *)data;

    g_thread_pool_set_max_threads(pool, 0, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(99), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(120), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(101), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(106), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(203), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(104), NULL);

    g_thread_pool_set_sort_function(pool, _test_thread_int_cmp_func, NULL);
    g_thread_pool_set_max_threads(pool, 1, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(TEST_THREAD_POOL_FIN), NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 4; //set initial max threads to 4

    GThread *thd = NULL;

    g_pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    thd = g_thread_new("thd", test_thread_func, g_pool);
    g_usleep(500*1000);
    g_thread_join(thd);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

运行结果:

[root@centos7_6 build]# ./glib_theadpool_set_sort_function_4_threads
tid 139887694608128: get data: 99 
tid 139887686215424: get data: 101 
tid 139887711393536: get data: 120 
tid 139887694608128: get data: 104 
tid 139887694608128: get data: 106 
tid 139887694608128: get data: 203 
tid 139887694608128: get data: 9999 
theadpool free 
[root@centos7_6 build]# ./glib_theadpool_set_sort_function_4_threads
tid 139875977897728: get data: 99 
tid 139875877648128: get data: 101 
tid 139875969505024: get data: 120 
tid 139875986290432: get data: 104 
tid 139875877648128: get data: 106 
tid 139875877648128: get data: 203 
tid 139875877648128: get data: 9999 
theadpool free 
[root@centos7_6 build]# ./glib_theadpool_set_sort_function_4_threads
tid 140545881827072: get data: 99 
tid 140545881827072: get data: 101 
tid 140545881827072: get data: 104 
tid 140545881827072: get data: 106 
tid 140545881827072: get data: 120 
tid 140545881827072: get data: 203 
tid 140545881827072: get data: 9999 
theadpool free

上述结果表明:
线程池执行任务时,创建的线程变得不确定起来,有可能是4个,有可能是3个,也有可能只有1个。原因是在线程池中创建线程也是需要消耗时间的,如果在线程创建之前就对线程池进行了g_thread_pool_set_max_threads(0),则新的线程就无法创建了。

下面用程序来验证一下。在线程池创建完后休眠50ms,再设置最大个数。
源码见glib_examples\glib_threadpool\glib_theadpool_set_sort_function_4_threads_sleep

#include <glib.h>
#include <pthread.h>

#define TEST_THREAD_POOL_FIN 9999

GThreadPool *g_pool = NULL;

gint _test_thread_int_cmp_func(gconstpointer a, gconstpointer b, gpointer user_data)
{
    return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("tid %ld: get data: %d \n", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free \n");
        g_thread_pool_free(g_pool, TRUE, TRUE);
    }
}

gpointer test_thread_func(gpointer data)
{
    GThreadPool *pool = (GThreadPool *)data;

    g_thread_pool_set_max_threads(pool, 0, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(99), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(120), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(101), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(106), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(203), NULL);
    g_thread_pool_push(pool, GINT_TO_POINTER(104), NULL);

    g_thread_pool_set_sort_function(pool, _test_thread_int_cmp_func, NULL);
    g_thread_pool_set_max_threads(pool, 1, NULL);

    g_thread_pool_push(pool, GINT_TO_POINTER(TEST_THREAD_POOL_FIN), NULL);

    return NULL;
}

void test_thread_pool(void)
{
    guint num = 0;
    GError *error = NULL;
    gint max_threads = 4;

    GThread *thd = NULL;

    g_pool = g_thread_pool_new(test_thread_pool_func, NULL, max_threads, TRUE, &error);

    g_usleep(50*1000); //sleep 50 ms, wait threadpool threads create

    thd = g_thread_new("thd", test_thread_func, g_pool);
    g_usleep(500*1000);
    g_thread_join(thd);
}

gint main(gint argc, gchar **argv)
{
    test_thread_pool();
}

运行结果:

[root@centos7_6 build]# ./glib_theadpool_set_sort_function_4_threads_sleep
tid 139845579298560: get data: 120 
tid 139845587691264: get data: 99 
tid 139845562513152: get data: 101 
tid 139845570905856: get data: 104 
tid 139845562513152: get data: 106 
tid 139845562513152: get data: 203 
tid 139845562513152: get data: 9999 
theadpool free 
[root@centos7_6 build]# ./glib_theadpool_set_sort_function_4_threads_sleep
tid 139912332961536: get data: 101 
tid 139912341354240: get data: 99 
tid 139912349746944: get data: 120 
tid 139912358139648: get data: 104 
tid 139912349746944: get data: 106 
tid 139912349746944: get data: 203 
tid 139912349746944: get data: 9999 
theadpool free 
[root@centos7_6 build]# ./glib_theadpool_set_sort_function_4_threads_sleep
tid 139784953247488: get data: 120 
tid 139784936462080: get data: 106 
tid 139784961640192: get data: 99 
tid 139784944854784: get data: 101 
tid 139784936462080: get data: 104 
tid 139784936462080: get data: 203 
tid 139784936462080: get data: 9999 
theadpool free

运行多次都可以发现,有4个线程被运行。需要注意的是任务排序结果仍不正确。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值