关于一个有3个线程的线程池相关操作(用作备忘)

Qt 6.5 串口多线程实战:moveToThread 与继承 QThread 的 3 种方案性能对比 本文深入探讨了Qt 6.5中串口多线程编程的三种实现方案,包括moveToThread事件驱动模型、继承QThread的同步处理以及混合模式异步队列。通过实测数据对比,分析了各方案在性能、资源占用和线程安全等方面的优劣,为开发者提供了高频串口数据处理场景下的优化建议和实战指南。重点解决了界面崩溃和多线程同步等核心挑战。 阅读详情

这个线程池的代码是从网上淘到的,经亲测是可以使用的。

#include <stdio.h> 

#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <pthread.h> 
#include <assert.h> 


/* 
*线程池里所有运行和等待的任务都是一个CThread_worker 
*由于所有任务都在链表里,所以是一个链表结构 
*/ 
typedef struct worker 
{ 
    /*回调函数,任务运行时会调用此函数,注意也可声明成其它形式*/ 
    void *(*process) (void *arg); 
    void *arg;/*回调函数的参数*/ 
    struct worker *next; 


} CThread_worker; 




/*线程池结构*/ 
typedef struct 
{ 
    pthread_mutex_t queue_lock; 
    pthread_cond_t queue_ready; 


    /*链表结构,线程池中所有等待任务*/ 
    CThread_worker *queue_head; 


    /*是否销毁线程池*/ 
    int shutdown; 
    pthread_t *threadid; 
    /*线程池中允许的活动线程数目*/ 
    int max_thread_num; 
    /*当前等待队列的任务数目*/ 
    int cur_queue_size; 


} CThread_pool; 




int pool_add_worker (void *(*process) (void *arg), void *arg); 
void *thread_routine (void *arg); 




static CThread_pool *pool = NULL; 
void pool_init (int max_thread_num) 
{ 
int i = 0;
    pool = (CThread_pool *) malloc (sizeof (CThread_pool)); 


    pthread_mutex_init (&(pool->queue_lock), NULL); 
    pthread_cond_init (&(pool->queue_ready), NULL); 


    pool->queue_head = NULL; 


    pool->max_thread_num = max_thread_num; 
    pool->cur_queue_size = 0; 


    pool->shutdown = 0; 


    pool->threadid = 
        (pthread_t *) malloc (max_thread_num * sizeof (pthread_t)); 
     
    for (i = 0; i < max_thread_num; i++) 
    {  
        pthread_create (&(pool->threadid[i]), NULL, thread_routine, 
                NULL); 
    } 
} 






/*向线程池中加入任务*/ 
int pool_add_worker (void *(*process) (void *arg), void *arg) 
{ 
    /*构造一个新任务*/ 
    CThread_worker *newworker = 
        (CThread_worker *) malloc (sizeof (CThread_worker)); 
    newworker->process = process; 
    newworker->arg = arg; 
    newworker->next = NULL;/*别忘置空*/ 


    pthread_mutex_lock (&(pool->queue_lock)); 
    /*将任务加入到等待队列中*/ 
    CThread_worker *member = pool->queue_head; 
    if (member != NULL) 
    { 
        while (member->next != NULL) 
            member = member->next; 
        member->next = newworker; 
    } 
    else 
    { 
        pool->queue_head = newworker; 
    } 


    assert (pool->queue_head != NULL); 


    pool->cur_queue_size++; 
    pthread_mutex_unlock (&(pool->queue_lock)); 
    /*好了,等待队列中有任务了,唤醒一个等待线程; 
    注意如果所有线程都在忙碌,这句没有任何作用*/ 
    pthread_cond_signal (&(pool->queue_ready)); 
    return 0; 
} 






/*销毁线程池,等待队列中的任务不会再被执行,但是正在运行的线程会一直 
把任务运行完后再退出*/ 
int pool_destroy () 
{ 
    if (pool->shutdown) 
        return -1;/*防止两次调用*/ 
    pool->shutdown = 1; 


    /*唤醒所有等待线程,线程池要销毁了*/ 
    pthread_cond_broadcast (&(pool->queue_ready)); 


    /*阻塞等待线程退出,否则就成僵尸了*/ 
    int i; 
    for (i = 0; i < pool->max_thread_num; i++) 
        pthread_join (pool->threadid[i], NULL); 
    free (pool->threadid); 


    /*销毁等待队列*/ 
    CThread_worker *head = NULL; 
    while (pool->queue_head != NULL) 
    { 
        head = pool->queue_head; 
        pool->queue_head = pool->queue_head->next; 
        free (head); 
    } 
    /*条件变量和互斥量也别忘了销毁*/ 
    pthread_mutex_destroy(&(pool->queue_lock)); 
    pthread_cond_destroy(&(pool->queue_ready)); 
     
    free (pool); 
    /*销毁后指针置空是个好习惯*/ 
    pool=NULL; 
    return 0; 
} 






void *thread_routine (void *arg) 
{ 
    printf ("starting thread 0x%x\n", (int)pthread_self()); 
    while (1) 
    { 
        pthread_mutex_lock (&(pool->queue_lock)); 
        /*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意 
        pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/ 
        while (pool->cur_queue_size == 0 && !pool->shutdown) 
        { 
            printf ("thread 0x%x is waiting\n", (int)pthread_self ()); 
            pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock)); 
        } 


        /*线程池要销毁了*/ 
        if (pool->shutdown) 
        { 
            /*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/ 
            pthread_mutex_unlock (&(pool->queue_lock)); 
            printf ("thread 0x%x will exit\n", (int)pthread_self ()); 
            pthread_exit (NULL); 
        } 


        printf ("thread 0x%x is starting to work\n", (int)pthread_self ()); 


        /*assert是调试的好帮手*/ 
        assert (pool->cur_queue_size != 0); 
        assert (pool->queue_head != NULL); 
         
        /*等待队列长度减去1,并取出链表中的头元素*/ 
        pool->cur_queue_size--; 
        CThread_worker *worker = pool->queue_head; 
        pool->queue_head = worker->next; 
        pthread_mutex_unlock (&(pool->queue_lock)); 


        /*调用回调函数,执行任务*/ 
        (*(worker->process)) (worker->arg); 
        free (worker); 
        worker = NULL; 
    } 
    /*这一句应该是不可达的*/ 
    pthread_exit (NULL); 
} 


    //下面是测试代码


void *myprocess (void *arg) 
{ 
    printf ("threadid is 0x%x, working on task %d\n", (int)pthread_self (),*(int *) arg); 
    sleep (1);/*休息一秒,延长任务的执行时间*/ 
    return NULL; 
} 


int main (int argc, char **argv) 
{ 
    pool_init (3);/*线程池中最多三个活动线程*/ 
     
    /*连续向池中投入10个任务*/ 
    int *workingnum = (int *) malloc (sizeof (int) * 10); 
    int i; 
    for (i = 0; i < 10; i++) 
    { 
        workingnum[i] = i; 
        pool_add_worker (myprocess, &workingnum[i]); 
    } 
    /*等待所有任务完成*/ 
    sleep (5); 
    /*销毁线程池*/ 
    pool_destroy (); 


    free (workingnum); 
    return 0; 
}
GD32F303调试小记(一)之USART(接收中断、接收空闲中断+DMA、发送DMA) 前言 之前写了GD32F103调试小记(二)之USART(接收中断、接收空闲中断+DMA、发送DMA)一文。这次我们来看看GD32F303的USART是如何配置的,结合这两篇文章,相信大家GD32的USART配置流程会十分熟悉。 DMA 能大大减轻CPU负荷的东西,建议场景合适的情况下,都去用DMA功能。 USART 一种串行通信协议, ... 阅读详情

相关推荐

从Canny到深度学习:边缘检测指标进化史(含ODS/OIS/AP的数学推导)

本文系统梳理了边缘检测评估指标的演进历程,从经典的Canny算子到深度学习时代,重点解析了ODS、OIS和AP三大核心指标的设计哲学与数学推导。文章深入探讨了基于PR曲线的评估体系,揭示了不同指标(如ODS与OIS)在阈值优化上的差异,并分析了AP指标在边缘检测任务中的优势与局限,为算法研究和模型评估提供了实用指南。

b9c0d的博客 199

创建多线程的四种方式 看完不懂,你来捶我!!!

线程(thread)是一个程序内部的一条执行路径。我们之前启动程序执行后,main方法的执行其实就是一条单独的执行路径,程序中如果只有一条执行路径,那么这个程序就是单线程的程序。多线程是指从软硬件上实现多条执行流程的技术。

m0_69901140的博客 2211

数据去重复_京东商品评论情感分析|文本数据预处理

本文爬取了十款热销手机的文本评论数据后,首先对文本评论数据做文本预处理,文本评论数据中存在大量的无价值信息,引入无用的文本数据,对其作情感分析,显然没有价值,得出的文本挖掘结果也不尽人意。所以对于文本评论数据先进行文本预处理是必不可少的一步,把大量的、冗余的、无价值的信息去除,可以极大提高文本数据的质量,精确文本分析结果。1 文本去重1.1文本去重的原因文本数据预处理时,首先应去除文本评论数据中反...

weixin_34556808的博客 2074

【Java线程池ThreadPool(创建线程的第三种方式)】

Java线程的创建方法

m0_72254454的博客 1151

线性代数知识点整理

线性代数基础知识点摘要整理

cuguanren的博客 3万+

MQTT(轻量级消息中间件)基本使用指南

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是一种轻量级的发布 / 订阅模式(Pub/Sub)消息传输协议,专为低带宽、不稳定网络环境设计,广泛应用于物联网(IoT)、移动设备、传感器网络等场景(如空气净化器、智能家居设备的远程控制)。Eclipse Mosquitto 是一款轻量级、开源的 MQTT 消息服务器(Broker),由 Eclipse 基金会维护,专为低资源消耗和易用性设计。

墨鸦的博客 1万+

线程池的几种常见的创建的方式

一:创建大小不固定的线程池 二:创建固定数量线程的线程池 三:创建单线程的线程池 四:创建定时线程 1.创建大小不固定的线程池 package com.peace.pms.Test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @Author: cxx ...

蓝星花 8669

国产射频直采收发器CX8242KA JESD204C调试

杭州诚芯公司的CX8242KA是国内开发的极少数支持JESD204C接口的高速AD、DA,Serdes具备支持接收和发送,并且速率可以到25Gbps,在国内属于领先水平。250M参考时钟输入,AD采样率2.5G,DA采样率10G,3收2发,主通道模式4,反馈通道模式1,基带采样率1250M,线速率20.625G,收发同时配置混频625M。CX8242KA的204C接口模式支持10种模式,在手册上都有说明。2、 支持TX信道编码,RX信道解码,提升健壮性。这里使用模式4,支持双通道模式,并且反馈开启。

RFSOC的博客 6221

多线程三创建线程池的4种方式

package com.gfk.thread; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService...

just love code 241

Windows下构建ImGui.Net

工具 Visual Studio 2017 操作 下载项目 git clone https://github.com/mellinoe/ImGui.NET.git 编译 右键以下两个项目并调试: ImGui.NET.SampleProgram ImGui.NET.SampleProgram.XNA Error fix 中间遇到一些问题: SDK版本不对 去微软官网下载安装对应版本 由于设置了代理被远程服务器拒绝连接 关闭代理(也许在环境变量中) nuget源无对应资源,404 NOT FOUN

jojozym的博客 1489

深入解析GEM5 McPAT NoC功耗模型:从arbiter电容计算到微架构关联

本文深入解析GEM5 McPAT NoC功耗模型,重点探讨arbiter电容计算与微架构的关联。通过拆解动态功耗公式和四类电容的物理本质,揭示能量与功率的转换关系,并提供参数调试和模型精度优化的实战技巧,帮助开发者更准确地预测和优化NoC功耗。

weixin_29305313的博客 201

Java 使用线程池执行多个任务的示例

这篇文章主要介绍了Java 使用线程池执行多个任务的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下 在执行一系列带有IO操作(例如下载文件),且互不相关的异步任务时,采用多线程可以很极大的提高运行效率。线程池包含了一系列的线程,并且可以管理这些线程。例如:创建线程,销毁线程等。本文将介绍如何使用Java中的线程池执行任务。 1 任务类型 在使用线程池执行任务之前,我们弄清楚什么任务可以被线程池调用。按照任务是否有返回值可以将任务分为两种,分别是实现Runnable的任务类(无参数无返回值

p1830095583的博客 5761

【我的Android进阶之旅】Android自定义View实现一个游戏摇杆,来实现监听遥动的方向或者监听摇动的角度的功能

一、需求描述 去年有个需求,需要使用自定义View实现一个游戏摇杆,来识别上下左右摇动的方向。 有点类似下面这样的王者荣耀游戏摇杆的效果 二、业界已有的参考资料 在下面这篇博客介绍了如何自定义游戏摇杆 2.1 博客介绍 Android自定义摇杆 2.1.1 功能 支持自适应大小 支持2个方向、4个方向、8个方向的摇动监听 支持摇动角度获取 可选回调模式 支持可摇动区域自定义 支持摇杆自定义 支持设置图片、色值、Shape图形 2.1.2 效果图 2.1.3 设置回调方式 setCallBac

字节卷动 1409

java线程池备忘录

In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing

sin_404的博客 217

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

堆栈花园的多线程学习备忘录——线程管理

一、线程组 1. 线程组的基本介绍 线程组就类似于在计算机中用文件夹管理文件,所以我们也可以用线程组来管理线程。在线程组中定义一组相似(相关)的线程,在线程组中同样也可以定义子线程组,就像文件夹里还有子文件夹一样。 Thread类有多个构造方法,允许我们在创建线程时,指定一个线程组,如果没有指定,那么这个线程就属于父线程所在的线程组,JVM在创建main线程时,会给它指定一个线程组,那么所有线程都一定会有一个线程组和它相关,线程有一个方法getThreadGroup()方法返回它的线程组。 线程组的设计是

堆栈花园的学习备忘录 167

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

线程的异常捕获与线程池的异常捕获

线程的异常捕获与线程池的异常捕获

p15097962069的博客 89

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java基础之线程、多线程

线程和进程、线程安全、死锁、强制启动、线程局部变量、堆和栈、获取线程堆栈、虚拟线程、start和run、Runnable和Callable、FutureTask、ForkJoinTask、interrupted和isInterrupted、 wait与sleep、wait-notify、生产者-消费者、notify和notifyAll、yield、检测线程是否拥有锁、竞态条件、ReadWriteLock、Semaphore、CyclicBarrier和CountDownLatch、 同步、volatile

lonelymanontheway的博客 1073

多线程的基础知识备忘

多线程 一、相关概念 1、程序: 是为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象。 2、进程: 是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程,有它自身的产生,存在和消亡的过程。-------生命周期 3、线程: 进程可进一步细化为线程,是一个程序内部的一条执行路径 线程分为用户线程和守护线程 **即:线程《线程(一个程序可以有多个线程) 程序:静态的代码 进程:动态执行的程序 线程:进程中要同时干几件事时,每一件事的执行路径成为线程。** 4、并行: 多个C

qq_44818523的博客 183

ThreadPoolExcutor 线程池 异常处理 (下篇)

ThreadPoolExcutor 线程池 异常处理 (下篇)

mhx123456789的博客 168

记一次线程池任务执行异常

记一次线程池任务执行异常

p15097962069的博客 203

Python设计模式编程中的备忘录模式与对象池模式示例

这篇文章主要介绍了Python设计模式编程中的备忘录模式与对象池模式,文中分别举了表单和线程的相关示例,需要的朋友可以参考下 Memento备忘录模式 备忘录模式一个最好想象的例子:undo! 它对对象的一个状态进行了’快照’, 在你需要的时候恢复原貌。做前端会有一个场景:你设计一个表单,当点击提交会对表单内容 验证,这个时候你就要对用户填写的数据复制下来,当用户填写的不正确或者格式不对等问题, ...

python编程基础教程 875

个人笔记 Java多线程(八)

这段笔记是参照b站教程BV1Rv411y7MU整理而来的,用于个人备忘以便复习,需要的朋友可以自取。 线程管理 1.线程组 类似于计算机中使用文件夹管理文件,可以使用线程组来管理线程。在线程组中定义一组相关(类似)的线程,在线程组中可以定义子线程组。 Thread类有几个构造方法允许在创建线程的时候指定线程组,如果在创建线程时没有指定线程租,则该线程则属于父线程所在的线程组。JVM在创建main线程的时候会为它指定一个线程组,因此每个Java线程都有一个与之相关联,可以调用getThreadGroup()方

qq_56781117的博客 252

java多线程框架 netty,JavaSocket编程之Netty框架线程模型

1.Netty概述Netty是一个由JBoss提供的高效的Java NIO client-server(客户端-服务器)开发框架,使用Netty可以快速开发网络应用。Netty提供了一种新的方式来使开发网络应用程序,使其很容易使用且有很强的可扩展性。Netty的内部实现是很复杂的,但是Netty提供了简单易用的API从网络处理代码中解耦业务逻辑。Netty是完全基于NIO实现的,采用事件驱动机制,...

weixin_42361026的博客 731

JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理

JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理

Littleree的博客 185

PYTHON__Thread达到上限的解决方案(设置线程上限)

PYTHON__Thread达到上限的解决方案(设置线程上限)

qq_38472451的博客 925

Netty高性能开发备忘录

原文转自Netty高性能开发备忘录-春天的旁边1. 连接篇1.1 Netty NativeNetty Native用C++编写JNI调用的Socket Transport,是由Twitter将Tomcat Native的移植过来,现在还时不时和汤姆家同步一下代码。经测试,的确比JDK NIO更省CPU。也许有人问,JDK的NIO也用EPOLL啊,大家有什么不同? Norman Maurer这么说的:

努力学习,认真工作 1328
上一篇: 以前写过的一个二叉树的代码 (作为备忘,完成度90%)
下一篇: 以前写的一个sniffer网络监听程序(作为备忘)
Zwarwolf
博客等级 码龄20年 693粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值