ACE - ACE_Task源码剖析及线程池实现
原文出自http://www.cnblogs.com/binchen-china,禁止转载。
上篇提到用Reactor模式,利用I/O复用,获得Socket数据并且实现I/O层单线程并发,和dispatch层把不同的I/O绑定到了不同的Event中去处理。也就是已经实现了多个client连接和通信,且可以把不同的I/O与Event句柄绑定,指定处理函数。
但是问题来了,多个用户连接时,I/O层可以通过复用以较快的速度处理连接和把过来的数据关联到绑定的Event函数执行。但是绑定Event函数获得数据后,需要逐个处理,当大量数据从I/O层过来,所有数据共享线程,而且业务代码又是非常耗时的。每个socket通道过来的数据都要以单线程的方式执行业务,效率就非常低了。必须当线程空闲时才能占有,所以这里有必要引入线程池去处理业务。
ACE_Task类封装了线程和消息队列,使这些功能以面向对象的方式提供给用户,其中消息队列并非IPC中的消息队列,在ACE实现实际为普通队列。利用ACE_Task可以生产一个或一组线程,并且为线程池之间的消息交互提供了接口和队列。在Event部分,我们可以利用线程池来解决效率问题。
下面提供线程池实现代码:
#include "ace/Task.h"
#include "ace/OS.h"
#include <string> using namespace std; string g_strMsg[] = {
"MESSAGE 1",
"MESSAGE 2",
"MESSAGE 3",
"MESSAGE 4",
"MESSAGE 5",
"MESSAGE 6",
}; class TaskThread: public ACE_Task<ACE_MT_SYNCH>
{
public:
virtual int svc(void)
{
ACE_Message_Block *Msg;// = new ACE_Message_Block();
while()
{
getq(Msg); //空闲线程阻塞
ACE_DEBUG((LM_INFO,"recevie msg:%s,time:%d\n",Msg->rd_ptr(),(int)ACE_OS::time()));
Msg->release(); //release
ACE_OS::sleep(); //延时1s模拟业务处理耗时
}
}
}; class Message
{
public:
Message(TaskThread* mb);
}; Message::Message(TaskThread* mb)
{
for (int i = ;i < ;++i)
{
string m_data = g_strMsg[i];
ACE_Message_Block* msg = new ACE_Message_Block(sizeof(m_data));
msg->copy(m_data.c_str());
mb->putq(msg); //put
}
} int main(int argc, char *argv[])
{
TaskThread task;
Message initMsg(&task);
task.activate(THR_NEW_LWP | THR_JOINABLE |THR_INHERIT_SCHED , );//创建10个线程
while();
return ;
}
修改线程数量进行测试:
10个线程效果:
3个线程效果:
1个线程效果:
有了这个ACE_TASK的demo,我们跟踪查看ACE源码。
在Task.cpp的ACE_Task_Base内的activate函数,可以看到线程是怎么创建出来的。
int
ACE_Task_Base::activate (long flags,
int n_threads,
int force_active,
long priority,
int grp_id,
ACE_Task_Base *task,
ACE_hthread_t thread_handles[],
void *stack[],
size_t stack_size[],
ACE_thread_t thread_ids[],
const char* thr_name[])
{
ACE_TRACE ("ACE_Task_Base::activate"); #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -); // If the task passed in is zero, we will use <this>
if (task == )
task = this; if (this->thr_count_ > && force_active == )
return ; // Already active.
else
{
if (this->thr_count_ > && this->grp_id_ != -)
// If we're joining an existing group of threads then make
// sure to use its group id.
grp_id = this->grp_id_;
this->thr_count_ += n_threads;
} // Use the ACE_Thread_Manager singleton if we're running as an
// active object and the caller didn't supply us with a
// Thread_Manager.
if (this->thr_mgr_ == )
# if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
this->thr_mgr_ = ACE_THREAD_MANAGER_SINGLETON::instance ();
# else /* ! ACE_THREAD_MANAGER_LACKS_STATICS */
this->thr_mgr_ = ACE_Thread_Manager::instance ();
# endif /* ACE_THREAD_MANAGER_LACKS_STATICS */ int grp_spawned = -;
if (thread_ids == )
// Thread Ids were not specified
grp_spawned =
this->thr_mgr_->spawn_n (n_threads,
&ACE_Task_Base::svc_run,
(void *) this,
flags,
priority,
grp_id,
task,
thread_handles,
stack,
stack_size,
thr_name);
else
// thread names were specified
grp_spawned =
this->thr_mgr_->spawn_n (thread_ids,
n_threads,
&ACE_Task_Base::svc_run,
(void *) this,
flags,
priority,
grp_id,
stack,
stack_size,
thread_handles,
task,
thr_name);
if (grp_spawned == -)
{
// If spawn_n fails, restore original thread count.
this->thr_count_ -= n_threads;
return -;
} if (this->grp_id_ == -)
this->grp_id_ = grp_spawned; #if defined (ACE_MVS) || defined(__TANDEM)
ACE_OS::memcpy( &this->last_thread_id_, '\0', sizeof(this->last_thread_id_));
#else
this->last_thread_id_ = ; // Reset to prevent inadvertant match on ID
#endif /* defined (ACE_MVS) */ return ; #else
{
// Keep the compiler from complaining.
ACE_UNUSED_ARG (flags);
ACE_UNUSED_ARG (n_threads);
ACE_UNUSED_ARG (force_active);
ACE_UNUSED_ARG (priority);
ACE_UNUSED_ARG (grp_id);
ACE_UNUSED_ARG (task);
ACE_UNUSED_ARG (thread_handles);
ACE_UNUSED_ARG (stack);
ACE_UNUSED_ARG (stack_size);
ACE_UNUSED_ARG (thread_ids);
ACE_UNUSED_ARG (thr_name);
ACE_NOTSUP_RETURN (-);
}
#endif /* ACE_MT_SAFE */
}
第49行,把线程执行函数指向了svc_run。
ACE_THR_FUNC_RETURN
ACE_Task_Base::svc_run (void *args)
{
ACE_TRACE ("ACE_Task_Base::svc_run"); ACE_Task_Base *t = (ACE_Task_Base *) args; // Register ourself with our <Thread_Manager>'s thread exit hook
// mechanism so that our close() hook will be sure to get invoked
// when this thread exits. #if defined ACE_HAS_SIG_C_FUNC
t->thr_mgr ()->at_exit (t, ACE_Task_Base_cleanup, );
#else
t->thr_mgr ()->at_exit (t, ACE_Task_Base::cleanup, );
#endif /* ACE_HAS_SIG_C_FUNC */ // Call the Task's svc() hook method.
int const svc_status = t->svc ();
ACE_THR_FUNC_RETURN status;
#if defined (ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN)
// Reinterpret case between integral types is not mentioned in the C++ spec
status = static_cast<ACE_THR_FUNC_RETURN> (svc_status);
#else
status = reinterpret_cast<ACE_THR_FUNC_RETURN> (svc_status);
#endif /* ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN */ // If we changed this zero change the other if in OS.cpp Thread_Adapter::invoke
#if 1
// Call the <Task->close> hook.
ACE_Thread_Manager *thr_mgr_ptr = t->thr_mgr (); // This calls the Task->close () hook.
t->cleanup (t, ); // This prevents a second invocation of the cleanup code
// (called later by <ACE_Thread_Manager::exit>.
thr_mgr_ptr->at_exit (t, , );
#endif
return status;
}
svc_run则在第19行调用了具体的我们在外部重写的虚函数函数执行。
下面是消息队列的维护,putq和getq在内联函数文件Task_T.inl内。
template <ACE_SYNCH_DECL> ACE_INLINE int
ACE_Task<ACE_SYNCH_USE>::getq (ACE_Message_Block *&mb, ACE_Time_Value *tv)
{
ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::getq");
return this->msg_queue_->dequeue_head (mb, tv);
} template <ACE_SYNCH_DECL> ACE_INLINE int
ACE_Task<ACE_SYNCH_USE>::putq (ACE_Message_Block *mb, ACE_Time_Value *tv)
{
ACE_TRACE ("ACE_Task<ACE_SYNCH_USE>::putq");
return this->msg_queue_->enqueue_tail (mb, tv);
}
实则就是在维护ACE_Task类里面的ACE_Message_Queue<ACE_SYNCH_USE> *msg_queue_;这个队列。
ACE_Task相对简单,里面关于线程池的创建和调度还是有很多值得学习的地方。
ACE - ACE_Task源码剖析及线程池实现的更多相关文章
- 源码剖析ThreadPoolExecutor线程池及阻塞队列
本文章对ThreadPoolExecutor线程池的底层源码进行分析,线程池如何起到了线程复用.又是如何进行维护我们的线程任务的呢?我们直接进入正题: 首先我们看一下ThreadPoolExecuto ...
- 【高并发】通过ThreadPoolExecutor类的源码深度解析线程池执行任务的核心流程
核心逻辑概述 ThreadPoolExecutor是Java线程池中最核心的类之一,它能够保证线程池按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态. ThreadPoolExecu ...
- Java并发包源码学习之线程池(一)ThreadPoolExecutor源码分析
Java中使用线程池技术一般都是使用Executors这个工厂类,它提供了非常简单方法来创建各种类型的线程池: public static ExecutorService newFixedThread ...
- SOFA 源码分析 — 自定义线程池原理
前言 在 SOFA-RPC 的官方介绍里,介绍了自定义线程池,可以为指定服务设置一个独立的业务线程池,和 SOFARPC 自身的业务线程池是隔离的.多个服务可以共用一个独立的线程池. API使用方式如 ...
- 深入源码分析Java线程池的实现原理
程序的运行,其本质上,是对系统资源(CPU.内存.磁盘.网络等等)的使用.如何高效的使用这些资源是我们编程优化演进的一个方向.今天说的线程池就是一种对CPU利用的优化手段. 通过学习线程池原理,明白所 ...
- 源码分析—ThreadPoolExecutor线程池三大问题及改进方案
前言 在一次聚会中,我和一个腾讯大佬聊起了池化技术,提及到java的线程池实现问题,我说这个我懂啊,然后巴拉巴拉说了一大堆,然后腾讯大佬问我说,那你知道线程池有什么缺陷吗?我顿时哑口无言,甘拜下风,所 ...
- Netty源码解析一——线程池模型之线程池NioEventLoopGroup
本文基础是需要有Netty的使用经验,如果没有编码经验,可以参考官网给的例子:https://netty.io/wiki/user-guide-for-4.x.html.另外本文也是针对的是Netty ...
- 从JDK源码角度看线程池原理
"池"技术对我们来说是非常熟悉的一个概念,它的引入是为了在某些场景下提高系统某些关键节点性能,最典型的例子就是数据库连接池,JDBC是一种服务供应接口(SPI),具体的数据库连接实 ...
- MYSQL 源码解读系列 [线程池。。] ----dennis的博客
http://blog.sina.com.cn/s/articlelist_1182000643_0_1.html
随机推荐
- noi 8780 拦截导弹
题目链接: http://noi.openjudge.cn/ch0206/8780/ LDS http://paste.ubuntu.com/23402528/
- [CCF] ISBN号码检测
CCF ISBN号码检测 题目概述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如"x-xxx-xxxxx-x",其 ...
- SQL SA密码丢失
------------记不清了,以下似乎是这样操作的-----NET STOP MSSQLSERVER Net Start MSSQLServer /m"SQLCMD" 安装并使 ...
- iOS 编码规范
Coding Guidelines for Cocoa https://developer.apple.com/library/prerelease/content/documentation/Coc ...
- Java 中文字符串编码之GBK转UTF-8
写过两篇关于编码的文章了,以为自己比较了解编码了呢?! 结果今天又结结实实的上了一课. 以前转来转去解决的问题终归还是简单的情形.即iso-8859-1转utf-8,或者iso-8859-1转gbk, ...
- centos7 gitlab
yum -y update chmod +x /etc/rc.d/rc.local vi /etc/selinux/config SELINUX=disabled reboot vi /etc/hos ...
- Windows Internals学习笔记(六)Windows关键系统组件
参考资料: 1. <Windows Internals> 2. Dependency Walker 3. Ntoskrnl.exe 4. Livekd的使用 5. WinDbg的使用(一) ...
- HTML5/CSS3hack
以下兼容技术我只测试了IE8+ Media Query 媒体查询 <script src="respond.min.js"></script> respon ...
- 用cython提升python的性能
Boosting performance with Cython Even with my old pc (AMD Athlon II, 3GB ram), I seldom run into ...
- react native get started run 模拟机报错解决
参照 http://reactnative.cn/docs/0.30/getting-started.html#content 1)当执行 react-native run-android 这个环节的 ...