十二、GLib——GThreadPool
1 GThreadPool基本概念
-
有时你希望异步地派发工作的执行,然后继续在自己的线程中工作。如果这种情况经常发生,每次启动和销毁线程的开销可能会太高。在这种情况下,重用已经启动的线程似乎是个不错的主意。确实如此,但是实现这一点可能很繁琐且容易出错。因此,GLib提供了线程池以方便你使用。另一个优势是,当不同的子系统使用GLib时,线程可以在它们之间共享。
-
要创建一个新的线程池,你可以使用g_thread_pool_new()。它可以通过g_thread_pool_free()来销毁。
-
如果你想在线程池中执行某个特定任务,可以调用g_thread_pool_push()。
-
要获取当前正在运行的线程数,可以调用g_thread_pool_get_num_threads()。
-
要获取仍未处理任务的数量,可以调用g_thread_pool_unprocessed()。
-
要控制线程池的最大线程数,可以使用g_thread_pool_get_max_threads()和g_thread_pool_set_max_threads()。
-
最后,你可以控制由GLib保留的未使用线程的数量。当前数量可以通过g_thread_pool_get_num_unused_threads()获取。最大数量可以通过g_thread_pool_get_max_unused_threads()和g_thread_pool_set_max_unused_threads()进行控制。可以通过调用g_thread_pool_stop_unused_threads()停止所有当前未使用的线程。
2 GThreadPool相关函数
/* filename: gthreadpool.h */
typedef struct _GThreadPool GThreadPool;
struct _GThreadPool
{
GFunc func;
gpointer user_data;
gboolean exclusive;
};
/* filename: gthreadpool.c */
typedef struct _GRealThreadPool GRealThreadPool;
struct _GRealThreadPool
{
GThreadPool pool;
GAsyncQueue *queue;
GCond cond;
gint max_threads; /* 线程池中最多能持有多少个线程 */
guint num_threads; /* 目前线程池中运行的线程数量(独有线程池 num_threads 等于 max_threads) */
gboolean running; /* 线程池是否运行,一般情况下都是 TRUE,只有 pool 释放后才是 FALSE */
gboolean immediate; /* 是否立即停止 */
gboolean waiting;
GCompareDataFunc sort_func;
gpointer sort_user_data;
};
-
GThreadPool
没有在类型系统注册,自定义结构体也没有实现引用计数。 -
g_thread_pool_new
创建线程池,g_thread_pool_free
释放线程池内存。
2.1 g_thread_pool_new ()
/**
* @brief: 创建线程池对象
* @func: 一个线程池对象其实只能运行一个函数,该变量就是线程池的线程中执行的函数,只不过线程执行的函数可以有不同的参数。
* @user_data: 每次调用时传递给 @func 的用户数据。
* @max_threads: 在新线程池中同时执行的最大线程数,-1 表示没有限制(独占线程池的时候,不能设置-1,因为独占线程池的时候,会立即创建相应的数量的线程)
* @exclusive: 是否应该是独占的线程池
* @error: 错误返回位置,或 %NULL
*/
GThreadPool *
g_thread_pool_new (GFunc func,
gpointer user_data,
gint max_threads,
gboolean exclusive,
GError **error);
2.1.1 关于exclusiv独占池的概念
-
如果设置
exclusive = TRUE
,线程池中的线程不会被其他线程所共享使用(如果线程池中的线程处于空闲状态也不会其共享使用),此时num_threads等于线程中最大线程数量。 -
如果设置
exclusive = FALSE
,线程池中的线程空闲时会被其他线程所共享使用,此时num_threads等于正在处理数据线程的数量,空闲线程不会计入其中。
2.2 g_thread_pool_free ()
/* 释放线程池内存 */
void
g_thread_pool_free (GThreadPool *pool,
gboolean immediate,
gboolean wait_);
2.3 g_thread_pool_push ()
/**
* @brief: 只有给线程池中push数据的时候,线程池中的函数才会执行,否则处于等待状态
*/
gboolean
g_thread_pool_push (GThreadPool *pool,
gpointer data,
GError **error)
2.4 g_thread_pool_unprocessed
/**
* @brief: 上一个push函数,push速度超过线程池线程处理速度,就会存在待处理数据
*/
guint
g_thread_pool_unprocessed (GThreadPool *pool);
2.5 g_thread_pool_get_num_threads
/**
* - 如果设置 `exclusive = TRUE`,线程池中的线程不会被其他线程所共享使用(如果线程池中的线程处于空闲状态也不会其共享使用),此时num_threads等于线程中最大线程数量。
* - 如果设置 `exclusive = FALSE`,线程池中的线程空闲时会被其他线程所共享使用,此时num_threads等于正在处理数据线程的数量,空闲线程不会计入其中。
*/
guint
g_thread_pool_get_num_threads (GThreadPool *pool);