用c语言实现android 的handler

所谓的同步并不是多个线程同时对内存进行访问,而是按照先后顺序依次进行的。线程同步的经典模型是生产者和消费者模型,读者写者问题,哲学家就餐问题。

C语言实现的生产者和消费者模型

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

// 链表的节点
struct Node
{
    int number;
    struct Node* next;
};

// 定义条件变量, 控制消费者线程
pthread_cond_t cond;
// 互斥锁变量
pthread_mutex_t mutex;
// 指向头结点的指针
struct Node * head = NULL;

// 生产者的回调函数
void* producer(void* arg)
{
    // 一直生产
    while(1)
    {
        pthread_mutex_lock(&mutex);
        // 创建一个链表的新节点
        struct Node* pnew = (struct Node*)malloc(sizeof(struct Node));
        // 节点初始化
        pnew->number = rand() % 1000;
        // 节点的连接, 添加到链表的头部, 新节点就新的头结点
        pnew->next = head;
        // head指针前移
        head = pnew;
        printf("+++producer, number = %d, tid = %ld\n", pnew->number, pthread_self());
        pthread_mutex_unlock(&mutex);

        // 生产了任务, 通知消费者消费
        pthread_cond_broadcast(&cond);

        // 生产慢一点
        sleep(rand() % 3);
    }
    return NULL;
}

// 消费者的回调函数
void* consumer(void* arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        // 一直消费, 删除链表中的一个节点
//        if(head == NULL)   // 这样写有bug
        while(head == NULL)
        {
            // 任务队列, 也就是链表中已经没有节点可以消费了
            // 消费者线程需要阻塞
            // 线程加互斥锁成功, 但是线程阻塞在这行代码上, 锁还没解开
            // 其他线程在访问这把锁的时候也会阻塞, 生产者也会阻塞 ==> 死锁
            // 这函数会自动将线程拥有的锁解开
            pthread_cond_wait(&cond, &mutex);
            // 当消费者线程解除阻塞之后, 会自动将这把锁锁上
            // 这时候当前这个线程又重新拥有了这把互斥锁
        }
        // 取出链表的头结点, 将其删除
        struct Node* pnode = head;
        printf("--consumer: number: %d, tid = %ld\n", pnode->number, pthread_self());
        head  = pnode->next;
        free(pnode);
        pthread_mutex_unlock(&mutex);        

        sleep(rand() % 3);
    }
    return NULL;
}

int main()
{
    // 初始化条件变量
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    // 创建5个生产者, 5个消费者
    pthread_t ptid[5];
    pthread_t ctid[5];
    for(int i=0; i<5; ++i)
    {
        pthread_create(&ptid[i], NULL, producer, NULL);
    }

    for(int i=0; i<5; ++i)
    {
        pthread_create(&ctid[i], NULL, consumer, NULL);
    }

    // 释放资源
    for(int i=0; i<5; ++i)
    {
        // 阻塞等待子线程退出
        pthread_join(ptid[i], NULL);
    }

    for(int i=0; i<5; ++i)
    {
        pthread_join(ctid[i], NULL);
    }

    // 销毁条件变量
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);

    return 0;
}

在此基础上实现 C 语言版的handler 机制:
handler.h

//
// Created by xshx on 2021/5/12.
//

#ifndef HANDLERTHREAD_HANDLER_H
#define HANDLERTHREAD_HANDLER_H
#include <pthread.h>

typedef  void*(*fun)(void *);
typedef  struct Message
{
    int messagID;
    fun  func;
    void* arg;
    Message* next;
}Message;

class Handler {

public:
    // 定义条件变量, 控制消费者线程
    pthread_cond_t cond;
// 互斥锁变量
    pthread_mutex_t mutex;
// 指向头结点的指针
    Message * head;
//  线程id
    pthread_t pid=0;

    Handler();

    void sendMessage(Message *message);
    static void* waitMessage(void *arg);
    void dispatchMessage();
    virtual void   handleMessage();
};

#endif //HANDLERTHREAD_HANDLER_H

handler.cpp

//
// Created by xshx on 2021/5/12.
//
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "Handler.h"

Handler::Handler() {
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    // 初始化条件变量
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    pthread_create(&pid, NULL, waitMessage, this);

}

void*  Handler::waitMessage(void *arg)
{
    Handler* pThis =(Handler*)arg;
    pThis->dispatchMessage();
}
void  Handler::dispatchMessage( )
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        // 一直消费, 删除链表中的一个节点
//        if(head == NULL)   // 这样写有bug
        while( head == NULL)
        {
            // 任务队列, 也就是链表中已经没有节点可以消费了
            // 消费者线程需要阻塞
            // 线程加互斥锁成功, 但是线程阻塞在这行代码上, 锁还没解开
            // 其他线程在访问这把锁的时候也会阻塞, 生产者也会阻塞 ==> 死锁
            // 这函数会自动将线程拥有的锁解开
            pthread_cond_wait(&cond, &mutex);
            // 当消费者线程解除阻塞之后, 会自动将这把锁锁上
            // 这时候当前这个线程又重新拥有了这把互斥锁
        }
        // 取出链表的头结点, 将其删除
        Message* pnode = head;
        printf("--dispatch Message: MessageID: %d, tid = %ld\n", pnode->messagID, pthread_self());
        pnode->func( pnode->arg );
        head  = pnode->next;
        free(pnode);
        pthread_mutex_unlock(&mutex);

        sleep(rand() % 3);
    }
    return ;
}


void Handler::sendMessage(Message *msg)
{
    printf("%s \n", __func__);

    // 一直生产
    pthread_mutex_lock(&mutex);
    // 创建一个链表的新节点
    Message* pnew = (Message*)malloc(sizeof(Message));
    // 节点初始化
    memcpy( pnew, msg, sizeof(Message));
    // 节点的连接, 添加到链表的头部, 新节点就新的头结点
    pnew->next = head;
    // head指针前移
    head = pnew;
    printf("++sendMessage, messageID = %d, tid = %ld\n", pnew->messagID, pthread_self());
    pthread_mutex_unlock(&mutex);

    // 生产了任务, 通知消费者消费
    pthread_cond_broadcast(&cond);

    // 生产慢一点
    sleep(rand() % 3);
    return ;
}


在main.cpp 文件中 我们可以这么使用。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include "Handler.h"
void* function(void *arg){
    char * str = (char *)arg;
    printf("%s \n", str);
}
int main()
{
//    HandlerThread *thread = new HandlerThread();
    char *hello = "hello handler";

    Handler *handler = new Handler();
    Message  message;
    message.messagID=2000;
    message.func = function;
    message.arg = hello;
    handler->sendMessage( &message);
    return 0;
}

这里实现的handler其实类似HandlerThread。

参考文章:
https://subingwen.cn/linux/thread-sync/
https://blog.csdn.net/hehao13956455/article/details/84638879

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值