在 《利用ACL库开发高并发半驻留式线程池程序》中介绍了如何使用 C 版本的 acl 线程库编写多线程程序,本文将会介绍如何使用 C++ 版本的 acl 线程库编写多线程程序,虽然 C++ 版 acl 线程库基于 C 版的线程库,但却提供了更为清晰简洁的接口定义(很多地方参考了 JAVA 的线程接口定义)。下面是一个简单的使用线程的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include "acl_cpp/lib_acl.hpp" class mythread : public acl::thread {public : mythread () {} ~mythread () {}protected : virtual void * run () { const char * myname = "run" ; printf ("%s: thread id: %lu, %lu\r\n" , myname, thread_id (), acl::thread::thread_self ()); return NULL ; } };static void test_thread (void ) { const char * myname = "test_thread" ; mythread thr; thr.set_detachable (false ); if (thr.start () == false ) { printf ("start thread failed\r\n" ); return ; } printf ("%s: thread id is %lu, main thread id: %lu\r\n" , myname, thr.thread_id (), acl::thread::thread_self ()); if (thr.wait (NULL ) == false ) printf ("wait thread failed\r\n" ); else printf ("wait thread ok\r\n" ); }int main (void ) { acl::acl_cpp_init (); test_thread ();#ifdef WIN32 printf ("enter any key to exit ...\r\n" ); getchar ();#endif return 0 ; }
从上面的示例来看,使用 acl 的线程库创建使用线程还是非常简单的。打开 lib_acl_cpp/include/acl_cpp/stdlib/thread.hpp 文件,可以看到线程类的声明,其中有两个基类:acl::thread 与 acl::thread_job,在 基类 acl::thread_job 中有一个纯虚函数 run(),acl::thread 也继承自 acl::thread_job,用户的线程类需要继承 acl::thread,并且需要实现基类 acl::thread_job 的纯虚函数: run()。当应用在主线程中调用线程实例的 start() 函数时,acl 线程库内部便创建一个子线程,子线程被创建后线程对象的 run() 函数便被调用。下面是 acl::thread 类中几个主要的方法定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class thread_job {public : thread_job () {} virtual ~thread_job () {} virtual void * run () = 0 ; };class thread : public thread_job {public : thread (); virtual ~thread (); bool start () ; bool wait (void ** out = NULL ) ; thread& set_detachable (bool yes) ; thread& set_stacksize (size_t size) ; unsigned long thread_id () const ; static unsigned long thread_self () ; .... };
从上面的线程示例及 acl::thread 的类定义,也许有人会觉得应该把 acl::thread_job 的纯虚方法:run() 放在 acl::thread 类中,甚至觉得 acl::thread_job 类是多余的,但是因为 acl 库中还支持线程池方式,则 acl::thread_job 就显得很有必要了。在 lib_acl_cpp\include\acl_cpp\stdlib\thread_pool.hpp 头文件中可以看到 acl 的线程池类 acl::thread_pool 的声明,该类的主要函数接口如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 class thread_pool { void start () ; void stop () ; void wait () ; bool run (thread_job* job) ; bool execute (thread_job* job) ; thread_pool& set_stacksize (size_t size) ; thread_pool& set_limit (size_t max) ; thread_pool& set_idle (int ttl) ; ...... };
这些接口定义也相对简单,下面给出一个使用线程池的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 class myjob : public acl::thread_job {public : myjob () {} ~myjob () {}protected : virtual void * run () { const char * myname = "run" ; printf ("%s: thread id: %lu\r\n" , myname, acl::thread::thread_self ()); return NULL ; } };class mythread_pool : public acl::thread_pool {public : mythread_pool () {} ~mythread_pool () { printf ("thread pool destroy now, tid: %lu\r\n" , acl::thread::thread_self ()); }protected : virtual bool thread_on_init () { const char * myname = "thread_on_init" ; printf ("%s: curr tid: %lu\r\n" , myname, acl::thread::thread_self ()); return true ; } virtual void thread_on_exit () { const char * myname = "thread_on_exit" ; printf ("%s: curr tid: %lu\r\n" , myname, acl::thread::thread_self ()); } };void test () { acl::thread_pool* threads = new mythread_pool (); threads->start (); acl::thread_job *job1= new myjob, *job2 = new myjob; threads->execute (job1); threads->execute (job2); threads->stop (); delete threads; delete job1; delete job2; }
如上例所示,在使用 acl 的C++版本线程池类库时,必须定义一个线程工作类(继承自 acl::thread_job)并实现基类的纯虚函数:run();另外,在使用线程池时,如果想要在线程创建时初始化一些线程局部变量以及在线程退出前释放一些线程局部变量,则可以定义 acl::thread_pool 的子类,实现基类中的 thread_on_init 和 thread_on_exit 方法,如果不需要,则可以直接使用 acl::thread_pool 类对象。
github:https://github.com/acl-dev/acl gitee:https://gitee.com/acl-dev/acl