C语言实现一个多线程委托模型

news/2024/10/31 3:21:57/

C语言实现一个多线程委托模型

多线程委托模型将线程分为boss线程(主线程)和worker线程(工作线程)。先从一个主线程开始运行,主线程根据情况完成工作线程的创建,将创建好的工作线程放入队列中,有工作时,主线程唤醒工作参与工作。如果工作线程产生异常,主线程可以关闭工作线程并开启新的工作线程。

以下是使用C语言实现多线程委托模型的代码,其中包含boss线程和worker线程,boss线程用于创建worker线程并将其放入工作队列中,有任务时唤醒worker线程:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>typedef struct {void *(*task)(void *arg);void *arg;
} Task;Task *task_create(void *(*task)(void *arg), void *arg);
void task_destroy(Task *task);typedef struct {int thread_count;int task_count;int head;int tail;Task **tasks;pthread_mutex_t mutex;pthread_cond_t done;
} ThreadPool;ThreadPool *threadpool_create(int thread_count, int task_count);
void threadpool_destroy(ThreadPool *pool);
void threadpool_add_task(ThreadPool *pool, void *(*task)(void *arg), void *arg);
Task *threadpool_get_task(ThreadPool *pool);
void *worker_thread(void *arg);Task *task_create(void *(*task)(void *arg), void *arg) {Task *t = (Task*) malloc(sizeof(Task));t->task = task;t->arg = arg;return t;
}void task_destroy(Task *task) {free(task); 
}ThreadPool *threadpool_create(int thread_count, int task_count) {ThreadPool *pool = (ThreadPool*) malloc(sizeof(ThreadPool));pool->thread_count = thread_count;pool->task_count = task_count;pool->head = pool->tail = 0;pool->tasks = (Task**) malloc(sizeof(Task*) * task_count);pthread_mutex_init(&pool->mutex, NULL);pthread_cond_init(&pool->done, NULL);int i;for (i = 0; i < pool->thread_count; i++) {pthread_t thread;pthread_create(&thread, NULL, worker_thread, pool);pthread_detach(thread);}return pool;
}void threadpool_destroy(ThreadPool *pool) {pthread_mutex_lock(&pool->mutex);int i;for (i = 0; i < pool->tail; i++) {task_destroy(pool->tasks[i]);}free(pool->tasks);free(pool);pthread_mutex_unlock(&pool->mutex);pthread_mutex_destroy(&pool->mutex);pthread_cond_destroy(&pool->done);
}void threadpool_add_task(ThreadPool *pool, void *(*task)(void *arg), void *arg) {pthread_mutex_lock(&pool->mutex);Task *t = task_create(task, arg);if (pool->tail == pool->task_count) {pool->task_count *= 2;pool->tasks = (Task**) realloc(pool->tasks, sizeof(Task*) * pool->task_count);}pool->tasks[pool->tail++] = t;pthread_cond_signal(&pool->done);pthread_mutex_unlock(&pool->mutex);
}Task *threadpool_get_task(ThreadPool *pool) {pthread_mutex_lock(&pool->mutex);while (pool->head == pool->tail) {pthread_cond_wait(&pool->done, &pool->mutex);}Task *t = pool->tasks[pool->head++];pthread_mutex_unlock(&pool->mutex);return t;
}void *worker_thread(void *arg) {ThreadPool *pool = (ThreadPool*) arg;for (;;) {Task *t = threadpool_get_task(pool);(*(t->task))(t->arg);task_destroy(t);}return NULL;
}void * boss_task(void *arg) {ThreadPool *pool = (ThreadPool*) arg;// 在boss线程中添加任务int i;for (i = 0; i < 10; i++) {threadpool_add_task(pool, worker_task, NULL);}return NULL;
}void * worker_task(void *arg) {printf("Worker thread running\n");return NULL;
}int main(int argc, char *argv[]) {ThreadPool *pool = threadpool_create(4, 10);threadpool_add_task(pool, boss_task, pool);sleep(10);threadpool_destroy(pool);return 0;
}

在这个示例中,我们定义了一个ThreadPool结构体,其中包括一个任务数组、一个锁和一个条件变量。worker_thread函数是用于执行任务的线程函数,而threadpool_createthreadpool_add_taskthreadpool_get_task函数用于创建、管理和调度任务。

main函数中,我们创建了一个包含4个线程、最大任务数量为10的线程池,并在其中添加了一个boss线程,用于向线程池中添加worker线程任务。在每个worker任务中,我们只输出一条消息,表示线程正在运行。

这就是一个使用C语言实现的多线程委托模型,其中包含了boss线程和worker线程。在实际使用时,应根据具体应用场景进行更进一步的修改和扩展。

如果工作线程产生异常,主线程可以关闭工作线程并开启新的工作线程

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>typedef struct {void *(*task)(void *arg);void *arg;
} Task;Task *task_create(void *(*task)(void *arg), void *arg);
void task_destroy(Task *task);typedef struct {int thread_count;int task_count;int head;int tail;Task **tasks;pthread_mutex_t mutex;pthread_cond_t done;
} ThreadPool;ThreadPool *threadpool_create(int thread_count, int task_count);
void threadpool_destroy(ThreadPool *pool);
void threadpool_add_task(ThreadPool *pool, void *(*task)(void *arg), void *arg);
Task *threadpool_get_task(ThreadPool *pool);
void *worker_thread(void *arg);Task *task_create(void *(*task)(void *arg), void *arg) {Task *t = (Task*) malloc(sizeof(Task));t->task = task;t->arg = arg;return t;
}void task_destroy(Task *task) {free(task);
}ThreadPool *threadpool_create(int thread_count, int task_count) {ThreadPool *pool = (ThreadPool*) malloc(sizeof(ThreadPool));pool->thread_count = thread_count;pool->task_count = task_count;pool->head = pool->tail = 0;pool->tasks = (Task**) malloc(sizeof(Task*) * task_count);pthread_mutex_init(&pool->mutex, NULL);pthread_cond_init(&pool->done, NULL);int i;for (i = 0; i < pool->thread_count; i++) {pthread_t thread;pthread_create(&thread, NULL, worker_thread, pool);pthread_detach(thread);}return pool;
}void threadpool_destroy(ThreadPool *pool) {pthread_mutex_lock(&pool->mutex);int i;for (i = 0; i < pool->tail; i++) {task_destroy(pool->tasks[i]);}free(pool->tasks);free(pool);pthread_mutex_unlock(&pool->mutex);pthread_mutex_destroy(&pool->mutex);pthread_cond_destroy(&pool->done);
}void threadpool_add_task(ThreadPool *pool, void *(*task)(void *arg), void *arg) {pthread_mutex_lock(&pool->mutex);Task *t = task_create(task, arg);if (pool->tail == pool->task_count) {pool->task_count *= 2;pool->tasks = (Task**) realloc(pool->tasks, sizeof(Task*) * pool->task_count);}pool->tasks[pool->tail++] = t;pthread_cond_signal(&pool->done);pthread_mutex_unlock(&pool->mutex);
}Task *threadpool_get_task(ThreadPool *pool) {pthread_mutex_lock(&pool->mutex);while (pool->head == pool->tail) {pthread_cond_wait(&pool->done, &pool->mutex);}Task *t = pool->tasks[pool->head++];pthread_mutex_unlock(&pool->mutex);return t;
}void *worker_thread(void *arg) {ThreadPool *pool = (ThreadPool*) arg;for (;;) {Task *t = threadpool_get_task(pool);int ret = 0;pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);ret = (*(t->task))(t->arg);pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);task_destroy(t);if (ret != 0) {pthread_mutex_lock(&pool->mutex);printf("Worker thread exited with error: %d\n", ret);pool->thread_count -= 1;pthread_mutex_unlock(&pool->mutex);pthread_exit(NULL);}}return NULL;
}void signal_handler(int signum) {// 忽略这里的信号处理函数
}void * boss_task(void *arg) {ThreadPool *pool = (ThreadPool*) arg;// 安装一个信号处理函数,方便关闭工作线程struct sigaction act;act.sa_handler = signal_handler;sigaction(SIGUSR1, &act, NULL);// 在boss线程中添加任务int i;for (i = 0; i < 10; i++) {threadpool_add_task(pool, worker_task, NULL);}return NULL;
}void * worker_task(void *arg) {int i;for (i = 0; i < 10; i++) {printf("Worker thread running: %d\n", i);sleep(1);// 模拟工作线程异常if (i == 5) {printf("Worker thread encountered an error\n");// 发送信号关闭工作线程pthread_kill(pthread_self(), SIGUSR1);return (void*) 1;}}return NULL;
}int main(int argc, char *argv[]) {ThreadPool *pool = threadpool_create(4, 10);threadpool_add_task(pool, boss_task, pool);// 运行10秒后退出sleep(10);// 关闭所有工作线程int i;for (i = 0; i < pool->thread_count; i++) {pthread_cancel(0);}threadpool_destroy(pool);return 0;
}

在这个示例中,我们基本上沿用了前面的代码,只是添加了处理工作线程异常的代码。我们在worker_thread函数中,通过调用pthread_setcancelstate函数禁止了线程被取消,然后执行工作任务,最后恢复线程的取消状态。如果线程执行任务时出现异常,我们在主线程中通过发送信号SIGUSR1来关闭工作线程。

在boss_task中添加的任务只是简单地输出一条消息,模拟了一些随机的操作。这里我们安装了一个信号处理函数,方便在工作线程内部发生异常时正确关闭线程。在main函数中,我们运行了10秒钟,然后通过pthread_cancel函数关闭了所有工作线程。

这就是一个使用C语言实现多线程委托模型的例子,其中包含boss线程和worker线程,可以处理工作线程的异常情况。从这个示例中,我们可以学到如何创建线程池,如何向线程池中添加任务,如何安全地关闭线程池,以及如何正确处理线程异常等知识。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器


http://www.ppmy.cn/news/92222.html

相关文章

使用object.defineProperty来更新数据示例

Object.defineProperty() 方法会直接在一个对象上定义一个新属性&#xff0c;或者修改一个对象的现有属性&#xff0c;并返回此对象。 Object.defineProperty&#xff08;&#xff09;可以为对象的属性添加特性&#xff0c;每一个被添加过的属性&#xff0c;都会拥有属于自己的…

Go完整即时通讯项目及Go的生态介绍

Go完整即时通讯项目 项目架构&#xff1a; 1 编写基本服务端-Server server.go package mainimport ("fmt""net" )// 定义服务端 type Server struct {ip stringport int }// 创建一个Server func NewServer(ip string, port int) *Server {return …

perl 通过 swig 调用 c++代码

Swig 是一个软件开发工具&#xff0c;可以简化不同语言与 C/C 的交互&#xff08;直接在其它语言的代码中调用 C/C 的代码&#xff09;。   记录一下成功用 perl 调用 c 代码的例子。 环境 操作系统&#xff1a;centos 7.9 perl: version 5.16.3 swig: version 2.0.10 g: v…

操作dom

1-获取元素 通过id、name、className属性获取&#xff0c;通过tagName获取&#xff1b; 通过id获取的是元素列表第一个&#xff1b;通过name属性获取的是NodeList&#xff1b;通过className和tagName获取的是HTMLCollection let son1 document.getElementById("son&quo…

C4D R26 渲染学习笔记(2):渲染流程介绍

往期文章 C4D R26 渲染学习笔记&#xff08;1&#xff09;&#xff1a;C4D版本选择和初始UI框介绍 3D建模流程 大致流程 #mermaid-svg-eE2RXHal49sVZ34l {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eE2RXHal4…

深度学习框架-Tensorflow2:特点、架构、应用和未来发展趋势

引言 深度学习是一种新兴的技术&#xff0c;已经在许多领域中得到广泛的应用&#xff0c;如计算机视觉、自然语言处理、语音识别等。在深度学习中&#xff0c;深度学习框架扮演着重要的角色。Tensorflow是一种广泛使用的深度学习框架&#xff0c;已经成为深度学习的事实标准。…

PLX31-EIP-MBTCP 以太网/IP到Modbus TCP/IP

PLX31-EIP-MBTCP ProSoft Technology的EtherNet/IP to Modbus TCP/IP通信网关允许在支持EtherNet/IP的控制器或设备与Modbus TCP/IP控制器或设备之间进行高速双向数据传输。 我们的Modbus TCP/IP驱动程序具有多种客户端和服务器功能&#xff0c;可实现更快的数据传输。此外&a…

自动清理 ES 历史数据

一、 背景 随着业务的增长和时间的变化&#xff0c;ES 数据库的存储空间越来越大&#xff0c;存储数据多数为系统监控日志&#xff0c;保存的数据不需要长期保留&#xff0c;多数情况只需要保留几个月ES数据即可&#xff0c;既可以减轻ES服务器的负载和资源使用率&#xff0c;还…