acl/samples/thread/thread_pool1/main.cpp
zsxxsz a3b2e1f6d1 优化了线程池的性能
通过给线程池中的每一个线程一个独立的线程条件变量(之前是用同一个),大大减少了线程池在任务调度时的竞争问题
2014-01-19 23:59:13 +08:00

243 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "lib_acl.h"
#include <assert.h>
/**
* 用户自定义数据结构
*/
typedef struct THREAD_CTX {
acl_pthread_pool_t *thr_pool;
int i;
} THREAD_CTX;
/* 全局性静态变量 */
static acl_pthread_pool_t *__thr_pool = NULL;
/* 线程局部存储变量(C99支持此种方式声明方便许多) */
static __thread unsigned int __local = 0;
static void free_buf_fn(void *arg)
{
ACL_VSTRING *buf = (ACL_VSTRING*) arg;
printf(">> current thread id=%u, buf = %s\r\n",
(unsigned int) acl_pthread_self(), acl_vstring_str(buf));
acl_vstring_free(buf);
}
static void worker_thread(void *arg)
{
THREAD_CTX *ctx = (THREAD_CTX*) arg; /* 获得用户自定义对象 */
unsigned int i = 0;
static __thread ACL_VSTRING *buf1 = NULL;
static __thread ACL_VSTRING *buf2 = NULL;
/* 仅是验证参数传递过程 */
assert(ctx->thr_pool == __thr_pool);
if (buf1 == NULL)
buf1 = acl_vstring_alloc(256);
if (buf2 == NULL)
buf2 = acl_vstring_alloc(256);
acl_vstring_sprintf(buf1, "buf1: tid=%u",
(unsigned int) acl_pthread_self());
acl_vstring_sprintf(buf2, "buf2: tid=%u",
(unsigned int) acl_pthread_self());
/* 注册函数,当该线程退出时自动释放 buf 内存空间 */
acl_pthread_atexit_add(buf1, free_buf_fn);
acl_pthread_atexit_add(buf2, free_buf_fn);
while (i < 5) {
if (__local != i)
acl_msg_fatal("__local=%d invalid", __local);
printf("thread id=%u, i=%d, __local=%d\r\n",
(unsigned int) acl_pthread_self(), ctx->i, __local);
i++;
/* 在本线程中将线程局部变量加1 */
__local++;
sleep(1);
}
acl_myfree(ctx);
/* 至此,该工作线程进入空闲状态,直到空闲超时退出 */
}
static int on_thread_init(void *arg)
{
const char *myname = "on_thread_init";
acl_pthread_pool_t *thr_pool = (acl_pthread_pool_t*) arg;
/* 判断一下,仅是为了验证参数传递过程 */
assert(thr_pool == __thr_pool);
printf("%s: thread(%u) init now\r\n", myname, (unsigned int) acl_pthread_self());
/* 返回0表示继续执行该线程获得的新任务返回-1表示停止执行该任务 */
return (0);
}
static void on_thread_exit(void *arg)
{
const char *myname = "on_thread_exit";
acl_pthread_pool_t *thr_pool = (acl_pthread_pool_t*) arg;
/* 判断一下,仅是为了验证参数传递过程 */
assert(thr_pool == __thr_pool);
printf("%s: thread(%u) exit now\r\n", myname, (unsigned int) acl_pthread_self());
}
static void run_thread_pool(acl_pthread_pool_t *thr_pool)
{
THREAD_CTX *ctx; /* 用户自定义参数 */
/* 设置全局静态变量 */
__thr_pool = thr_pool;
/* 设置线程开始时的回调函数 */
(void) acl_pthread_pool_atinit(thr_pool, on_thread_init, thr_pool);
/* 设置线程退出时的回调函数 */
(void) acl_pthread_pool_atfree(thr_pool, on_thread_exit, thr_pool);
ctx = (THREAD_CTX*) acl_mycalloc(1, sizeof(THREAD_CTX));
assert(ctx);
ctx->thr_pool = thr_pool;
ctx->i = 0;
/**
* 向线程池中添加第一个任务,即启动第一个工作线程
* @param wq 线程池句柄
* @param worker_thread 工作线程的回调函数
* @param event_type 此处写0即可
* @param ctx 用户定义参数
*/
acl_pthread_pool_add(thr_pool, worker_thread, ctx);
sleep(1);
ctx = (THREAD_CTX*) acl_mycalloc(1, sizeof(THREAD_CTX));
assert(ctx);
ctx->thr_pool = thr_pool;
ctx->i = 1;
/* 向线程池中添加第二个任务,即启动第二个工作线程 */
acl_pthread_pool_add(thr_pool, worker_thread, ctx);
}
static void main_thread_atexit(void *arg)
{
ACL_VSTRING *buf = (ACL_VSTRING*) arg;
printf("main thread exit now, tid=%u, buf=%s\r\n",
(unsigned int) acl_pthread_self(), acl_vstring_str(buf));
printf("in the main thread_atexit, input any key to exit\r\n");
getchar();
}
static acl_pthread_pool_t *thr_pool_create(int threads, int timeout)
{
acl_pthread_pool_attr_t attr;
acl_pthread_pool_t *thr_pool;
acl_pthread_pool_attr_init(&attr);
acl_pthread_pool_attr_set_threads_limit(&attr, threads);
acl_pthread_pool_attr_set_idle_timeout(&attr, timeout);
/* 创建半驻留线程句柄 */
thr_pool = acl_pthread_pool_create(&attr);
assert(thr_pool);
return (thr_pool);
}
typedef struct {
ACL_VSTREAM *fp;
int i;
} RUN_CTX;
static acl_pthread_mutex_t __mutex;
static int __i = 0;
static void run_thread(void *arg)
{
RUN_CTX *ctx = (RUN_CTX*) arg;
acl_pthread_mutex_lock(&__mutex);
if (0)
acl_vstream_fprintf(ctx->fp, "hello world, id: %d, i: %d\n", ctx->i, __i++);
else
__i++;
acl_pthread_mutex_unlock(&__mutex);
acl_myfree(ctx);
}
static void test_thread_pool(void)
{
acl_pthread_pool_t *thr_pool;
ACL_VSTREAM *fp = acl_vstream_fopen("test.log", O_WRONLY | O_CREAT, 0600, 4096);
int i;
acl_pthread_mutex_init(&__mutex, NULL);
thr_pool = acl_thread_pool_create(100, 10);
for (i = 0; i < 1000000; i++) {
RUN_CTX *ctx = (RUN_CTX*) acl_mymalloc(sizeof(RUN_CTX));
ctx->fp = fp;
ctx->i = i;
acl_pthread_pool_add(thr_pool, run_thread, ctx);
}
acl_pthread_pool_destroy(thr_pool);
acl_pthread_mutex_destroy(&__mutex);
acl_vstream_close(fp);
printf("last i: %d\r\n", __i);
}
int main(int argc acl_unused, char *argv[] acl_unused)
{
acl_pthread_pool_t *thr_pool;
int max_threads = 20; /* 最多并发20个线程 */
int idle_timeout = 10; /* 每个工作线程空闲10秒后自动退出 */
static __thread ACL_VSTRING *buf = NULL;
if (1) {
test_thread_pool();
exit (0);
}
buf = acl_vstring_alloc(256);
acl_vstring_sprintf(buf, "in main thread, id=%u",
(unsigned int) acl_pthread_self());
acl_pthread_atexit_add(buf, main_thread_atexit);
thr_pool = thr_pool_create(max_threads, idle_timeout);
run_thread_pool(thr_pool);
if (0) {
/* 如果立即运行 acl_pthread_pool_destroy则由于调用了线程池销毁函数
* 主线程便立刻通知空闲线程退出,所有空闲线程不必等待空闲超时时间便可退出,
*/
printf("> wait all threads to be idle and free thread pool\r\n");
/* 立即销毁线程池 */
acl_pthread_pool_destroy(thr_pool);
} else {
/* 因为不立即调用 acl_pthread_pool_destroy所有所有空闲线程都是当空闲
* 超时时间到达后才退出
*/
while (1) {
int ret;
ret = acl_pthread_pool_size(thr_pool);
if (ret == 0)
break;
printf("> current threads in thread pool is: %d\r\n", ret);
sleep(1);
}
/* 线程池中的工作线程数为0时销毁线程池 */
printf("> all worker thread exit now\r\n");
acl_pthread_pool_destroy(thr_pool);
}
/* 主线程等待用户在终端输入任意字符后退出 */
printf("> enter any key to exit\r\n");
getchar();
return (0);
}