news 2026/7/13 21:23:00

用 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/7/14 6:02:39

使用Qwen3-14B进行法律文书辅助撰写的合规性探讨

使用Qwen3-14B进行法律文书辅助撰写的合规性探讨 在律师事务所的某个深夜&#xff0c;一位年轻律师正为第二天开庭的案件赶制答辩状。他反复核对《民法典》条文、比对类似判例、调整措辞逻辑——这本是再普通不过的一幕&#xff0c;但如今&#xff0c;这样的场景正悄然发生变化…

作者头像 李华
网站建设 2026/7/14 6:02:40

2025 网安副业入门:5 个低门槛方向,零基础也能接的第一单

2025 网安副业入门&#xff1a;5 个低门槛方向&#xff0c;零基础也能接的第一单 “学了半个月 Kali&#xff0c;想赚点外快却不知道从哪下手”“怕技术不够接不了单&#xff0c;又怕定价太高没人要”—— 这是 90% 网安新手想做副业时的共同困境。2025 年网安副业市场需求旺盛…

作者头像 李华
网站建设 2026/7/13 14:59:22

WebSocket实时通讯完整指南:从基础到生产级应用

引言在现代Web应用开发中&#xff0c;实时通讯已经成为不可或缺的功能。无论是聊天应用、实时数据监控&#xff0c;还是在线游戏&#xff0c;WebSocket都扮演着重要角色。本文将基于Vue3项目&#xff0c;详细介绍如何实现一个生产级的WebSocket实时通讯方案。一、WebSocket基础…

作者头像 李华
网站建设 2026/7/14 6:18:07

43、Unix 手册页与文件系统全面解析

Unix 手册页与文件系统全面解析 1. 手册页语法检查 在 Unix 系统中,检查手册页的正确格式通常有多种方式。可以通过打印输出来直观检查,使用的命令如下: - groff -man -Tps pathfind.man | lp - troff -man -Tpost pathfind.man | /usr/lib/lp/postscript/dpost | lp…

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

大模型+数据治理=解放双手!AI Agent编程实战,让代码自己会思考

引言 当“人治”成为数据治理的最大瓶颈&#xff0c; AI Agent 正在成为那根撬动变革的杠杆。 在企业数字化浪潮中&#xff0c;“数据治理”早已不是新鲜词。但现实却令人无奈&#xff1a;制度写得再完善&#xff0c;执行仍靠人&#xff1b;流程设计再精细&#xff0c;落地总…

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

AI干货:多模态大模型技术演进全解析!从CLIP到Qwen3-Omni,三条技术路线重塑AI开发范式,小白也能看懂的AI革命!

导语 从视觉与语言的初步对齐&#xff0c;到跨模态理解与生成的深度融合&#xff0c;多模态大语言模型&#xff08;Multimodal LLM&#xff09;的演进正以前所未有的速度重塑人机交互的边界。 回溯这一技术脉络&#xff0c;CLIP 首次通过对比学习在海量图文数据中建立起语义对…

作者头像 李华