news 2026/4/23 12:37:54

用 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/4/23 9:45:40

34、使用 awk 实现简单拼写检查器

使用 awk 实现简单拼写检查器 在文本处理中,拼写检查是一项常见且重要的任务。本文将详细介绍如何使用 awk 语言实现一个简单的拼写检查器,包括字典的加载、命令行选项的处理、后缀规则的应用等关键步骤,并给出完整的代码示例。 1. 字典的获取 在编写拼写检查器时,首先需…

作者头像 李华
网站建设 2026/4/23 9:44:28

Stata 18 多元统计 + 数据管理 让数据分析更专业安装教程

前言 Stata 18 该版本在历代版本基础上&#xff0c;聚焦因果推断、元分析、生存分析等核心研究领域&#xff0c;全面强化统计分析能力&#xff0c;同时优化数据管理、图表制作与结果报告等功能模块&#xff0c;广泛适用于经济学、医学、社会学等学科的实证研究工作。 版本亮点…

作者头像 李华
网站建设 2026/4/23 9:45:35

48、Unix 技术知识全解析:从基础命令到前沿概念

Unix 技术知识全解析:从基础命令到前沿概念 1. 重要 Unix 命令 在 Unix 系统中,存在众多用于进程管理和文件操作的重要命令,这些命令是系统操作的基础。 - 进程相关命令 :包括用于创建、删除或管理进程的命令,如 at 可在指定时间执行作业, batch 会在系统负载不…

作者头像 李华
网站建设 2026/4/23 9:45:57

别再乱选了!LLM应用实时通信技术SSE、WebSocket、WebRTC全方位对比

一、核心技术原理剖析 在为大型语言模型&#xff08;LLM&#xff09;应用构建实时前后端通信系统时&#xff0c;选择正确的底层技术至关重要。本章节将深入剖析三种主流技术的核心原理&#xff1a; Server-Sent Events (SSE)&#xff0c;它作为服务器主导的单向数据流的黄金标…

作者头像 李华
网站建设 2026/4/23 9:46:54

MySQL MOD()函数详解与Python对比

✅ 一、MySQL 的 MOD() 函数是怎么计算的&#xff1f;MOD(x, y) 是取余数的操作&#xff0c;即&#xff1a; &#x1f449; x % y&#xff08;在数学上就是 x 除以 y 的余数&#xff09;&#x1f50d; 示例解析&#xff1a;SELECT MOD(31, 8), MOD(234, 0), MOD(46.6, 6);表达式…

作者头像 李华