在libevent中使用线程池
一 线程的初始化
1线程对象
在进行事件驱动时,每个线程需建立自己的事件根基。由于libevent未提供线程之间通信的方式,我们采用管道来进行线程的通信。同时为方便主线程分配线程,我们还需保留各个线程的id号。因此我们采用如下结构来保留每个线程的有关信息。
pthread_t thread_id; //线程ID
struct event_base *base; //事件根基
struct event notify_event;
int notify_receive_fd;
int notify_send_fd;
CQ new_conn_queue; //连接队列
} LIBEVENT_THREAD;
2 初始化线程
我们先介绍如何为每个线程创建自己的事件根基。正如前面介绍的我们需自己建立管道来进行线程通信,因此在线程根基初始化后,我们为为管道的读添加事件对象。注意:在libevent中,线程的初始化需在事件根基初始化之后(即event_init之后)。
if (! me->base)
me->base = event_init();
event_set(&me->notify_event, me->notify_receive_fd,
EV_READ | EV_PERSIST, thread_libevent_process, me);
event_base_set(me->base, &me->notify_event);
event_add(&me->notify_event, 0) == -1)
cq_init(&me->new_conn_queue);
}
将主线程存储于结构体的第0个对象中,然后为每个线程创建管道并创建事件根基
threads[0].base = main_base;
threads[0].thread_id = pthread_self();
for (i = 0; i < nthreads; i++) {
int fds[2];
pipe(fds)
threads[i].notify_receive_fd = fds[0];
threads[i].notify_send_fd = fds[1];
setup_thread(&threads[i]);
接下来从主线程中创建线程,线程创建成功后激活该线程的事件根基,进入事件循环。
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&thread, &attr, worker_libevent, &threads[i])
}
二 分发连接
现在我们有了多个线程和事件根基,那么我们应该如何将主线程接收到的连接分发给各个线程并将其激活呢?本例子中线程的选择采用最简单的轮询方式。
我们需要对accept_handle函数进行修改。在线程池模型中,我们使用子线程代替主线程来创建缓冲区事件对象,主线程只是对激活选中的线程。我们通过向管道写入一个空字节来激活该管道的读请求。
thread += 1;
item->sfd = sfd
cq_push(&threads[thread].new_conn_queue, item);
write(threads[thread].notify_send_fd, "", 1)
三 处理请求
管道的读请求就绪后,回调函数thread_libevent_process被调用,此时就进入到了线程中,后面所有的调度都将在该线程中进行。
首先从管道中读取1个字节,然后创建事件缓冲区对象来实际处理请求。
static void thread_libevent_process(int fd, short which, void *arg) {
char buf[1];
read(fd, buf, 1)
…
}
四结束语
到这里我们的程序就可以使用线程池和libevent事件驱动来协同工作了。在实际的服务中,我们通常要将服务作为守护进程来运行,那么在linux中,如何编写守护进程呢?后面在继续学习如何编写linux守护进程。
在libevent中使用线程池相关推荐
- Java5中的线程池实例讲解
Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活.本文通过一个网络服务器模型,来实践Java5的多线程 ...
- java mina多线程_mina2中的线程池
一.Mina中的线程池模型 前面介绍了Mina总体的层次结构,那么在Mina里面是怎么使用Java NIO和进行线程调度的呢?这是提高IO处理性能的关键所在.Mina的线程调度原理主要如下图所示: A ...
- Java-Java中的线程池原理分析及使用
文章目录 概述 线程池的优点 线程池的实现原理 线程池的使用 创建线程池 向线程池中提交任务 关闭线程池 合理的配置线程池 线程池的监控 概述 我们在上篇博文 Java-多线程框架Executor解读 ...
- python停止线程池_详解python中Threadpool线程池任务终止示例代码
需求 加入我们需要处理一串个位数(0~9),奇数时需要循环打印它:偶数则等待对应时长并完成所有任务:0则是错误,但不需要终止任务,可以自定义一些处理. 关键点 定义func函数处理需求 callbac ...
- 四十七、面试前,必须搞懂Java中的线程池ThreadPoolExecutor(上篇)
@Author:Runsen @Date:2020/6/9 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...
- android中的线程池学习笔记
阅读书籍: Android开发艺术探索 Android开发进阶从小工到专家 对线程池原理的简单理解: 创建多个线程并且进行管理,提交的任务会被线程池指派给其中的线程进行执行,通过线程池的统一调度和管理 ...
- 多线程线程池的实现java_如何在Java中实现线程池
多线程线程池的实现java 线程是独立程序的执行路径. 在java中,每个线程都扩展java.lang.Thread类或实现java.lang.Runnable. 多线程是指在一个任务中同时执行两个或 ...
- 如何在Java中实现线程池
线程是独立程序的执行路径. 在java中,每个线程都扩展java.lang.Thread类或实现java.lang.Runnable. 多线程是指在一个任务中同时执行两个或多个线程.在多线程中,每个任 ...
- java线程池怎么创建_java中的线程池,如何创建?
Java中的线程池它是线程的容器,或者(换句话说,它是具有执行任务能力的线程的集合). 我们可以使用ThreadPool框架来定位(或实现)线程池. 线程池可以包含多个线程.每当我们执行任何任务时,线 ...
最新文章
- mysql带DISTINCT 关键字的查询
- [Noip模拟赛] Polygon
- 天气模式_江西现罕见持续阴雨寡照天气 市民开启“花式吐槽”模式
- 正则表达式简明使用手册
- SalesOrder Text determination
- centos7安装DHCP服务器
- .NETCore_生成实体
- bem什么意思_BEM命名法
- update 千万数据_mysql学习(四)数据库
- RocketMq发送延迟消息
- Exp-00009错误解決
- 蓝桥杯练习题:保留100位小数的黄金分割数
- 源码--常用的人脸识别数据库
- luaprofiler探索
- 数据库在线自生成ER图
- matlab多行注释快捷键。
- linux其他命令(查找文件、软链接、硬链接)
- 330tsl是什么意思_19款探岳330tsl两区豪华型怎么样?
- QT<八> 绘图事件、绘图设备
- 【开源代码】在criteo数据集用MLP跑出AUC=0.809的结果
热门文章
- sentinel 时间窗口的实现
- caffeine 弱引用key的实现
- 纯CSS: hover特效
- CentOS+Nginx一步一步开始配置负载均衡
- Android给文档加水印,Android文档水印之PDF水印
- 垃圾回收算法与实现系列-String在虚拟机中的实现
- [eclipse]Syntax error on token ;,{ expected after this token
- 关于如何收集,标准化和集中化处理Golang日志的一些建议
- Springboot整合netty实战
- 同步工具之CountDownLatch闭锁