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

2023-05-16

简介

线程池是在多线程编程时经常用到的技术。在进行多线程任务处理时,如果线程频繁创建和销毁,将会使系统开销变大,在这种情况下,上一个任务执行完后不销毁之前创建的线程,后续任务重用该线程,将会大大减小开销。为了管理这些创建之后不再销毁的线程,便有了线程池的概念。
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_examplesglib_threadpoolglib_threadpool_push

#include <glib.h>

static void test_thread_pool_func(gpointer data, gpointer user_data)
{
    g_print("get data: %d 
", 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_examplesglib_threadpoolglib_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 
", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free 
");
        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_examplesglib_threadpoolglib_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 
", 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_examplesglib_threadpoolglib_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 
");
        return;
    }

    ret_val = foobar->func(foobar->foo, foobar->bar);
    g_print("ret_val: %d 
", 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_examplesglib_threadpoolglib_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 
", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free 
");
        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 
");
    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 
", g_thread_pool_unprocessed(pool));
    g_print("max threads: %d 
", g_thread_pool_get_max_threads(pool));
    g_print("num threads: %d 
", g_thread_pool_get_num_threads(pool));
    g_print("num unused threads: %d 
", g_thread_pool_get_num_unused_threads());
    g_print("max unused threads: %d 
", 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_examplesglib_threadpoolglib_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 
", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free 
");
        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_examplesglib_threadpoolglib_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 
", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free 
");
        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_examplesglib_threadpoolglib_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 
", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free 
");
        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_examplesglib_threadpoolglib_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 
", (glong)pthread_self(), GPOINTER_TO_INT(data));

    g_usleep(50*1000);

    if(TEST_THREAD_POOL_FIN == GPOINTER_TO_INT(data)) {
        g_print("theadpool free 
");
        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个线程被运行。需要注意的是任务排序结果仍不正确。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

5_04_GLib库入门与实践_线程池 的相关文章

  • nodeinternalmodulescjsloader936 throw err; 求解决

    D ethereumDkfuwq gt node app js node internal modules cjs loader 936 throw err Error Cannot find module safe buffer Requ
  • Tomcat 下载安装教程

    文章目录 参考资料1 下载2 安装3 卸载4 启动5 关闭6 配置7 部署8 IDEA使用Tomcat 8 1 集成本地Tomcat8 2 Tomcat Maven插件 参考资料 视频 使用Tomcat的前提是你已经熟练Java xff0c
  • JS说古道今

    JS说古道今 本文概要 讲述js的来源及重要的语法特性 xff0c 包括数据类型 DOM 作用域等 xff08 由于专业性比较强就不写诗扯淡了 61 61 xff0c 我尽量写的有趣点吧 JS JSP xff1f JavaScript xf
  • 删除集合当中的空元素(Collections.singleton(null)与stream())

    Arrays asList创建的数据为定长集合 xff0c 集合长度在操作时是不可以改变的 xff0c 不能对集合进行增删操作 Collections singleton null 相关 span class token comment 反
  • RabbitMQ配置更改TCP默认端口5672

    前言 公司新项目需集成RabbitMQ xff0c 但服务器环境已经安装了ActiveMQ 今天同事不说还不知道 xff0c 导致安装后俩MQ打架 端口冲突 而发生的一系列问题 没办法 xff0c 后来居上的就很被动 xff0c 于是就得改
  • WebSocket服务端消息推送

    前言 xff1a 移动互联网蓬勃发展的今天 xff0c 大部分手机 APP和网站都提供了消息推送功能 xff0c 如新闻客户端的热点新闻推荐 xff0c IM 工具的聊天消息提醒 xff0c 电商产品促销信息 xff0c 企业应用的通知和审
  • tomcat7下载

    百度网盘下载 xff1a 链接 xff1a https pan baidu com s 1qbaxHo0dEdL9JC08yzbL6Q 提取码 xff1a ysz9
  • Springboot查看日志

    Springboot查看日志 以前用springMVC时查看日志直接进入tail f out 但是用了springboot之后 xff0c 一时不知道如何实现 xff0c 记录一下 以下以log4j2为日志框架 先在log4j2 xml中添
  • 爬取CSDN专栏文章到本地,并保存为html、pdf、md格式

    前言 突然想爬取CSDN的专栏文章到本地保存了 xff0c 为了影响小一点 xff0c 特地挑选CSDN的首页进行展示 综合资讯这一测试点是什么找到的呢 xff1f 就是点击下图的热点文章 xff0c 然后跳转到具体文章 xff0c 然后再
  • Spring入门第一讲——Spring框架的快速入门

    Spring的概述 什么是Spring xff1f 我们可以从度娘上看到这样有关Spring的介绍 xff1a 说得更加详细一点 xff0c Spring是一个开源框架 xff0c Spring是于2003年兴起的一个轻量级的Java开发框
  • 手动清理RabbitMq队列中的消息

    一 手动删除队列中指定个数的消息 打开RabbitMq管理页面 xff0c 进入队列 点击 Get messages Requeue 改成No Mesaages 设置一个值 点击Get messages 二 一次清理队列中的所有消息 打开R
  • 关于Spring核心配置文件中的各项主要配置

    1 xff1a Spring的核心配置文件中的各种配置 spring的核心配置文件的名字 叫做 applicationContext xml xff0c 后期也可以通过配置文件修改名称 xff0c 在web xml中进行如下修改 xff1a
  • JVM内存设置

    对于jvm的设置我一直知道的很少 xff0c 有时候遇到outOfMemoryError只会一个简单的设置 Xms256m Xmx512m 有几个问题一直没搞明白 xff1a 1 jvm的内存大小究竟应该设置成多少最合适 xff1f 2 j
  • 闭包,一个浪漫的故事

    闭包 xff0c 一个浪漫的故事 前 今天稍微说一下js中的闭包 xff0c 这是个新手很少遇到的老手不常遇到的问题 xff0c 他的出现主要是为了帮我们规避问题 xff0c 另外提供了一种解决问题的新途径 xff0c 这里先说明一点啊 x
  • vue中集成jsplumb报错`Cannot read property ‘parentNode‘ of null`,且无法渲染连线的问题

    简介 我在项目中使用了typescript 43 vue 43 jsplumb作为流程图框架 问题 我在容器中使用的是v for指令渲染 从配置文件中读取流程图的json并且存入this items变量中通过v for指令 xff0c 调用
  • [webpack-cli] Invalid options object. Dev Server has been initialized using an options object

    问题内容 xff1a webpack cli Invalid options object Dev Server has been initialized using an options object that does not matc
  • 使用idea创建web项目

    前言 xff1a 很高兴能够用自己所学知识为你提供答疑 xff01 xff01 xff01 今天我就来操作下如何使用idea这款软件创建web项目 步骤 xff1a 1 创建项目 首先新建一个项目 然后选择最后一个 xff0c 创建一个空白
  • 基于若依开发管理项目中引入工作流引擎activiti7,包含前后端(原创)

    原项目中用到了工作流引擎 xff0c 使用若依框架开发 xff0c 原二开使用项目 xff1a https gitee com y project RuoYi Vue 基于activiti7地址 xff1a https gitee com
  • 最新方法VScode中html代码自动补全(超清晰详细,保证能用)

    一 下载HTML Snippets插件 二 配置settings json 1 在VScode窗口下按住ctrl 43 shift 43 P xff0c 调出搜索框 xff0c 在搜索框中输入settings json xff0c 选择打开
  • 计算机毕业设计-基于SpringBoot+Vue的新冠疫苗预约接种管理系统

    计算机毕业设计 基于SpringBoot 43 Vue的新冠疫苗预约接种管理系统 1 开发环境及工具下载 开发语言 xff1a Java架构 xff1a B S框架 xff1a SpringBoot 43 vue数据库 xff1a MySQ

随机推荐