news 2026/8/7 0:50:55

用 C 实现一个简化版 MessageQueue

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 C 实现一个简化版 MessageQueue

Android 的 MessageQueue 很复杂(native poll/epoll、barrier、idle handler…)
但它的核心思想非常简单
✅ 一个队列存消息
✅ 一个循环不断取消息执行
✅ 线程安全(加锁/条件变量)

我们用 C 写一个可跑的简化版

  • 支持post(msg)

  • 支持loop()阻塞取消息

  • 支持quit()退出

1)数据结构:消息节点 + 队列

typedef struct Message { int what; void (*callback)(int what); // 收到消息后执行的回调 struct Message* next; } Message; typedef struct { Message* head; Message* tail; int quit; pthread_mutex_t mutex; pthread_cond_t cond; } MessageQueue;

2)队列初始化 / 销毁

void mq_init(MessageQueue* q){ q->head = q->tail = NULL; q->quit = 0; pthread_mutex_init(&q->mutex, NULL); pthread_cond_init(&q->cond, NULL); } void mq_destroy(MessageQueue* q){ pthread_mutex_lock(&q->mutex); Message* cur = q->head; while(cur){ Message* next = cur->next; free(cur); cur = next; } q->head = q->tail = NULL; pthread_mutex_unlock(&q->mutex); pthread_mutex_destroy(&q->mutex); pthread_cond_destroy(&q->cond); }

3)post:入队 + 唤醒 loop

void mq_post(MessageQueue* q, int what, void (*cb)(int)){ Message* m = (Message*)malloc(sizeof(Message)); m->what = what; m->callback = cb; m->next = NULL; pthread_mutex_lock(&q->mutex); if(q->tail == NULL){ q->head = q->tail = m; }else{ q->tail->next = m; q->tail = m; } pthread_cond_signal(&q->cond); // 通知消费者 pthread_mutex_unlock(&q->mutex); }

4)next:阻塞取消息(队列空就等)

Message* mq_next(MessageQueue* q){ pthread_mutex_lock(&q->mutex); while(!q->quit && q->head == NULL){ pthread_cond_wait(&q->cond, &q->mutex); } if(q->quit){ pthread_mutex_unlock(&q->mutex); return NULL; } Message* m = q->head; q->head = m->next; if(q->head == NULL) q->tail = NULL; pthread_mutex_unlock(&q->mutex); return m; }

5)loop:像 Looper 一样执行消息

void mq_loop(MessageQueue* q){ while(1){ Message* m = mq_next(q); if(m == NULL) break; if(m->callback){ m->callback(m->what); } free(m); } }

6)quit:让 loop 退出

void mq_quit(MessageQueue* q){ pthread_mutex_lock(&q->mutex); q->quit = 1; pthread_cond_broadcast(&q->cond); pthread_mutex_unlock(&q->mutex); }

7)完整可运行 Demo(Linux / macOS)

编译:gcc mq.c -o mq -lpthread

#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> typedef struct Message { int what; void (*callback)(int what); struct Message* next; } Message; typedef struct { Message* head; Message* tail; int quit; pthread_mutex_t mutex; pthread_cond_t cond; } MessageQueue; void mq_init(MessageQueue* q){ q->head = q->tail = NULL; q->quit = 0; pthread_mutex_init(&q->mutex, NULL); pthread_cond_init(&q->cond, NULL); } void mq_post(MessageQueue* q, int what, void (*cb)(int)){ Message* m = (Message*)malloc(sizeof(Message)); m->what = what; m->callback = cb; m->next = NULL; pthread_mutex_lock(&q->mutex); if(q->tail == NULL){ q->head = q->tail = m; }else{ q->tail->next = m; q->tail = m; } pthread_cond_signal(&q->cond); pthread_mutex_unlock(&q->mutex); } Message* mq_next(MessageQueue* q){ pthread_mutex_lock(&q->mutex); while(!q->quit && q->head == NULL){ pthread_cond_wait(&q->cond, &q->mutex); } if(q->quit){ pthread_mutex_unlock(&q->mutex); return NULL; } Message* m = q->head; q->head = m->next; if(q->head == NULL) q->tail = NULL; pthread_mutex_unlock(&q->mutex); return m; } void mq_quit(MessageQueue* q){ pthread_mutex_lock(&q->mutex); q->quit = 1; pthread_cond_broadcast(&q->cond); pthread_mutex_unlock(&q->mutex); } void mq_loop(MessageQueue* q){ while(1){ Message* m = mq_next(q); if(m == NULL) break; if(m->callback) m->callback(m->what); free(m); } } void mq_destroy(MessageQueue* q){ pthread_mutex_lock(&q->mutex); Message* cur = q->head; while(cur){ Message* next = cur->next; free(cur); cur = next; } q->head = q->tail = NULL; pthread_mutex_unlock(&q->mutex); pthread_mutex_destroy(&q->mutex); pthread_cond_destroy(&q->cond); } void on_msg(int what){ printf("handle msg what=%d (thread=%lu)\n", what, (unsigned long)pthread_self()); } typedef struct { MessageQueue* q; } ProducerArg; void* producer(void* arg){ ProducerArg* pa = (ProducerArg*)arg; for(int i=1;i<=5;i++){ mq_post(pa->q, i, on_msg); usleep(200 * 1000); } mq_quit(pa->q); return NULL; } int main(){ MessageQueue q; mq_init(&q); pthread_t t; ProducerArg pa = { .q = &q }; pthread_create(&t, NULL, producer, &pa); mq_loop(&q); pthread_join(t, NULL); mq_destroy(&q); return 0; }

8)这跟 Android MessageQueue 的对应关系

  • mq_postenqueueMessage
  • mq_nextnext()
  • mq_loopLooper.loop()
  • cond_wait≈ “没有消息就阻塞等待”
  • quitLooper.quit()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/7 14:19:23

缓存与数据库一致性解决方案深度解析

一、业务场景与挑战1.1 12306余票查询场景在12306系统中&#xff0c;用户需要实时查询列车不同站点、不同座位类型的余票信息。为提升查询性能&#xff0c;我们将余票信息缓存在Redis中。但在用户下单支付时&#xff0c;需要同时更新数据库和缓存中的余票数据。核心挑战&#x…

作者头像 李华
网站建设 2026/8/7 15:52:58

消息队列真仙:我的道念支持最终一致性

瑶池圣地&#xff0c;飞升台。九天罡风如刀&#xff0c;撕扯着白玉砌成的古老平台。万丈雷云在头顶凝聚&#xff0c;电蛇狂舞&#xff0c;酝酿着最后一重、也是最凶险的“九霄寂灭神雷”。台下&#xff0c;瑶池众仙娥、各方观礼道友&#xff0c;皆屏息凝神&#xff0c;目光聚焦…

作者头像 李华
网站建设 2026/8/7 23:02:24

Spring Boot项目推送Gitee全流程(进阶)

对于国内的Java开发者而言&#xff0c;将Spring Boot项目托管到Gitee是一个常见且高效的选择。本文将以IntelliJ IDEA为开发环境&#xff0c;手把手带你完成从项目初始化到代码成功推送的全过程&#xff0c;并澄清关键概念、解释核心命令&#xff0c;助你彻底掌握。 一、核心概…

作者头像 李华
网站建设 2026/8/7 14:28:27

Java毕设项目:基于Springboot大学校园自习室教室座位预约网站设计与实现基于springboot高校自习室预约系统的设计与实现(源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/8/7 22:09:40

JAVA打造同城羽馆预约,一键畅享运动

利用 JAVA 开发同城羽毛球馆预约系统&#xff0c;可以结合 高并发处理、实时交互、多端适配 等特性&#xff0c;打造一个 “一键预约、智能匹配、全流程数字化” 的运动服务平台&#xff0c;让用户轻松畅享羽毛球运动的乐趣。以下是具体实现方案与核心功能设计&#xff1a;一、…

作者头像 李华
网站建设 2026/8/7 14:58:17

经验贴 | 科学制定招聘需求与预算:HR 必看的逻辑与实操要点

招聘是企业补充人才、保障发展的核心环节&#xff0c;而科学制定招聘需求与预算则是招聘工作高效落地的前提。不少 HR 在实际工作中会陷入 “需求模糊导致招聘偏差”“预算失控造成资源浪费” 的困境&#xff0c;既影响招聘效率&#xff0c;也难以匹配业务发展诉求。本文结合实…

作者头像 李华