彻底搞清楚多线程编程

很多时候在主线程中运行的程序需要一个while true,但是这样会导致程序整体上非常庞大,引入多线程来减少主线程的内容,同时也能顺利的实现功能,还有一个问题在于多线程还可以一定程度上减少全局变量(但是也是需要反复运行反复获得return,没有全局变量用着舒服)

多线程编程的作用就是上面所描述的哪些,那么如何编写一个可控的msg呢?

Emergency_brake_threading = threading.Thread(target=emergency_brake_decision)    

其中emergency_brake_decision为

def emergency_brake_decision1():while not rospy.is_shutdown():print("1")

一个线程不是说反复会执行自己的函数,而是执行本函数。如果当前函数是一个循环,那就是会一个执行循环中的内容的,所以说,不要想当然就认为线程就是一个无限执行一个函数,而是单独在启动线程后可以同时执行启动的线程的函数,其运行情况由其本身决定
完整来说:

import threading
import timedef thread_prc1(a):print(a)def thread_prc2(b,a):print(b)
a=0
b=1while a<100:a+=1b+=2Threading_prc1 = threading.Thread(target=thread_prc1,args=(a,))Threading_prc2 = threading.Thread(target=thread_prc2,args=(b,a))#启动Threading_prc1.start()Threading_prc2.start()#等待结束Threading_prc1.join()Threading_prc2.join()

线程默认是一直执行的,直到线程函数结束或者线程被显式地停止或中断。Threading_prc1线程会执行 thread_prc1函数,并将a作为参数传递给函数。这是一个最简单的线程。循环可以写在线程里面也可以在外面,如果希望它是反复执行的话。

然后就是如果线程有返回值的问题了,线程有返回值其实就是说明线程已经执行完一次了,如果不希望他影响主频率,那么它的执行速度必须也是很快的。而且循环要写在外面:

import threading
import time
b=1class MyThread(threading.Thread):def __init__(self, target, args=()):super().__init__(target=target, args=args)self.result = Nonedef run(self):self.result = self._target(*self._args)def thread_prc1(a):k = 1k+=1print(a)return kdef thread_prc2():global bprint(b)def main():global ba=0while a<100:a+=1b+=2Threading_prc1 = MyThread(target=thread_prc1,args=(a,))Threading_prc2 = threading.Thread(target=thread_prc2)#启动Threading_prc1.start()Threading_prc2.start()#等待结束Threading_prc1.join()##每次结束后都有返回值:result = Threading_prc1.resultprint("k",result)print("b",b)Threading_prc2.join()if __name__ == "__main__":main()

注意,threading.Thread是没有办法拿到返回值的,所以其实还是需要全局变量,虽然可以用自己定义的MyThread拿到返回值,不过基本也不这么干。
最最后,是一个用时间变化的线程去改变车辆速度:在这里插入代码片

### !/usr/bin/python3
# -*- coding: utf-8 -*-##减速测试 base_wirecontrol
import time
import matplotlib.pyplot as pltimport can
import cantools
import rospy
import time
import std_msgs.msg
from car_interfaces.msg import CarOriInterface,PathSpeedCtrlInterface
import os
import signal
import json
import threadingbrake_flag = False
Brake = False
Brake_end = Falseflag_steer = 0
q_num = 0
quit_mod = False
is_exit = False
start_flag = False
target_vel = 0#17  #车辆速度设置
target_steer_vel = 50  # 车辆方向盘转角速度
num = 0
bus_vel = 0
veh_cte = 0vel_plan = 0flag_end = 0 #终点停车只执行一次flag_spd_start = 1#状态转换
flag_spd_start_brake = 1#状态转换y = 0import os
import sys
# 获取当前脚本文件的所在目录
script_directory = os.path.dirname(os.path.abspath(__file__))
# 图片文件相对于脚本文件的路径
image_relative_path = 'lib'
# 构建图片文件的完整路径
icon_path = os.path.join(script_directory, image_relative_path)
# absolute_path = os.path.abspath(icon_path)# print(absolute_path)
sys.path.append(icon_path)
from base_function import *
class MyThread(threading.Thread):def __init__(self, target, args=()):super().__init__(target=target, args=args)self.result = Nonedef run(self):self.result = self._target(*self._args)def signal_handler(signal, frame):global is_exitis_exit = Truemessages_1 = [      # 发送给整车VCU的报文类型{'message_id': 0x0C01D0A5,    # 车辆方向盘转向信息报文'message_name': 'steering_control','signals': {'target_steering_angle': 0,     # 车辆方向盘角度,两字节表示'target_steering_mod': 5,       # 车辆转向控制模式,4 bit表示,置1为转角控制模式,若手动后,则置5后再置1'DCU_valid': 1,                 # VCU状态,1为正常,0为不正常,1 bit表示'steering_control_valid': 1,    # 车辆转角状态,1为正常,0不正常,1 bit表示'target_steering_torque': 0,    # 转向叠加扭矩信号,目前可以先取128中间值,一字节表示'target_steering_velocity': target_steer_vel,  # 方向盘目标角速度,5-54对应50 ~ 540°/s,分辨率为10,一字节表示'steering_msg_life': 0,         # 该消息发送的生命周期}},{'message_id': 0x0C02D0A5,   # 车辆qudong信息报文'message_name': 'drive_control','signals': {'target_velocity': target_vel,'target_acceleration': 0,'target_direction': 1,'fault_code': 0,'drive_msg_life': 0,}},{'message_id': 0x0C03D0A5,  # 车辆zhidong# 信息报文'message_name': 'barke_control','signals': {'target_deceleration': 0,'XBR2_EBI_Mode': 0,'XBR2_Priority': 0,'XBR2_Ctrl_Mode': 0,'XBR2_message_counter': 0,'XBR2_checksum': 0,}},{'message_id': 0x0C04D0A5,  # 车辆整车速度信息报文'message_name': 'body_control','signals': {'mode_disp': 0,'body_state': 1,'turning_lighting_control': 0,'high_low_beam_control': 2,'hazard_lights_control': 0,'backup_light_control': 0,'width_lamp_control': 0,'wiper_wash_switch' : 0,'front_door_control': 0,'middle_door_control': 0,'horn_control' : 0,}},{'message_id': 0x0C08D0A5,  # 车辆整车速度信息报文'message_name': 'parking_control','signals': {'longterm_park_req': 0,'temp_park_req': 0,'park_control_mode': 0,'park_work_mode': 0,'park_air_pressure': 0,'temp_park_pressure': 0,'park_msg_checksum': 10,}},
]def msg_send_to_vcu(messages_1,dbc,bus):#置发送了messageglobal countglobal brake_flagglobal bus_vel# 以下向车辆VCU发送了方向盘转角规划信息global flag_steerglobal Brakeglobal q_numglobal quit_modglobal steer_modglobal count1msg_send = dbc.get_message_by_name(messages_1[0]['message_name'])messages_ = list(msg_send.encode(messages_1[0]['signals']))messages_send = can.Message(arbitration_id=msg_send.frame_id, data=messages_, is_extended_id=True)msg_send11 = dbc.get_message_by_name(messages_1[1]['message_name'])messages_11 = list(msg_send11.encode(messages_1[1]['signals']))messages_send11 = can.Message(arbitration_id=msg_send11.frame_id, data=messages_11, is_extended_id=True)msg_send33 = dbc.get_message_by_name(messages_1[2]['message_name'])messages_33 = list(msg_send33.encode(messages_1[2]['signals']))messages_send33 = can.Message(arbitration_id=msg_send33.frame_id, data=messages_33, is_extended_id=True)msg_send44 = dbc.get_message_by_name(messages_1[3]['message_name'])messages_44 = list(msg_send44.encode(messages_1[3]['signals']))messages_send44 = can.Message(arbitration_id=msg_send44.frame_id, data=messages_44, is_extended_id=True)msg_send88 = dbc.get_message_by_name(messages_1[4]['message_name'])messages_88 = list(msg_send88.encode(messages_1[4]['signals']))messages_send88 = can.Message(arbitration_id=msg_send88.frame_id, data=messages_88, is_extended_id=True)bus.send(messages_send)bus.send(messages_send11)bus.send(messages_send33)bus.send(messages_send44)bus.send(messages_send88)def msg_recv_from_vcu(dbc,bus):     # 从整车VCU中得到车辆目前实际相关信息,并放入到信息meg_car_ori中global bus_velglobal steer_modglobal quit_modglobal messages_1global countglobal count1global brake_flagglobal q_numglobal target_velglobal vel_planmessages_recv = bus.recv()drive_life = messages_1[1]['signals']['drive_msg_life']drive_life += 1if drive_life > 255:drive_life -= 256messages_1[1]['signals']['drive_msg_life'] = drive_lifepark_life = messages_1[4]['signals']['park_msg_checksum']park_life += 1if park_life > 255:park_life -= 256messages_1[4]['signals']['park_msg_checksum'] = park_lifeif start_flag:messages_1[3]['signals']['mode_disp'] = 1else:messages_1[3]['signals']['mode_disp'] = 0messages_1[1]['signals']['target_velocity'] = 0if messages_1[0]['signals']['target_steering_mod'] == 5:messages_1[1]['signals']['target_velocity'] = 0q_num += 1if q_num >= 20:messages_1[0]['signals']['target_steering_mod'] = 1# print(messages_1[0]['signals']['target_steering_mod'],"k"*12)#当前速度if messages_recv.arbitration_id == 0x0C06A5D0:decoded_messages = dbc.decode_message(messages_recv.arbitration_id, messages_recv.data)bus_vel = decoded_messages['act_vehicle_velocity']    def can_stop_thread(dbc, bus):global messages_2messages_2 = [      # 发送给整车VCU的报文类型{'message_id': 0x0C01D0A5,    # 车辆方向盘转向信息报文'message_name': 'steering_control','signals': {'target_steering_angle': 0,     # 车辆方向盘角度,两字节表示'target_steering_mod': 5,       # 车辆转向控制模式,4 bit表示,置1为转角控制模式,若手动后,则置5后再置1'DCU_valid': 1,                 # VCU状态,1为正常,0为不正常,1 bit表示'steering_control_valid': 1,    # 车辆转角状态,1为正常,0不正常,1 bit表示'target_steering_torque': 0,    # 转向叠加扭矩信号,目前可以先取128中间值,一字节表示'target_steering_velocity': 300,  # 方向盘目标角速度,5-54对应50 ~ 540°/s,分辨率为10,一字节表示'steering_msg_life': 0,         # 该消息发送的生命周期}},{'message_id': 0x0C02D0A5,   # 车辆qudong信息报文'message_name': 'drive_control','signals': {'target_velocity': 0,'target_acceleration': 0,'target_direction': 1,'fault_code': 0,'drive_msg_life': 0,}},{'message_id': 0x0C03D0A5,  # 车辆zhidong# 信息报文'message_name': 'barke_control','signals': {'target_deceleration': 0,'XBR2_EBI_Mode': 0,'XBR2_Priority': 0,'XBR2_Ctrl_Mode': 0,'XBR2_message_counter': 0,'XBR2_checksum': 0,}},{'message_id': 0x0C04D0A5,  # 车辆整车速度信息报文'message_name': 'body_control','signals': {'mode_disp': 0,'body_state': 1,'turning_lighting_control': 0,'high_low_beam_control': 0,'hazard_lights_control': 0,'backup_light_control': 0,'width_lamp_control': 0,'wiper_wash_switch' : 0,'front_door_control': 0,'middle_door_control': 0,'horn_control' : 0,}},{'message_id': 0x0C08D0A5,  # 车辆整车速度信息报文'message_name': 'parking_control','signals': {'longterm_park_req': 0,'temp_park_req': 0,'park_control_mode': 0,'park_work_mode': 0,'park_air_pressure': 0,'temp_park_pressure': 0,'park_msg_checksum': 10,}},]msg_send_to_vcu(messages_2, dbc, bus)bus.shutdown()print('\nall threads were ended by Ctrl-C')def speed_change_brake(interval,total_time):global y #速度start_time = time.time()time_list = []y_list = []k = 0# 循环计算并记录时间和 y 的值while True:# 计算经过的时间elapsed_time = time.time() - start_time# 检查是否超过总运行时间,如果超过则跳出循环if elapsed_time <= total_time:  ##5s加速到10y = 10t = elapsed_time  # 时间变量y_list.append(y)time_list.append(t)# print(elapsed_time)elif y >= -0.1:if k==0:k = 1start_time_ = time.time()time_ = time.time() - start_time_# 计算 y 的值t = time_  # 时间变量if y <= 0:y = 0else:y = -1 * t + 10if y <0:y=0# print(time_)# 记录时间和 y 的值time_list.append(t)y_list.append(y)if y <= 0 and time_ > 15:breakprGreen(time_)result = y_list# 等待一段时间,控制循环速率time.sleep(interval)prRed(y)return resultdef prRed(skk): print("\033[91m {}\033[00m".format(skk))def prGreen(skk): print("\033[92m {}\033[00m".format(skk))def prYellow(skk): print("\033[93m {}\033[00m".format(skk))def prBlue(skk): print("\033[94m {}\033[00m".format(skk))
def prPurple(skk): print("\033[95m {}\033[00m".format(skk))
def prCyan(skk): print("\033[96m {}\033[00m".format(skk))def prOrange(skk): print("\033[33m {}\033[00m".format(skk))def prPink(skk): print("\033[95m {}\033[00m".format(skk))def main():global is_exitglobal yflag_wire = 0signal.signal(signal.SIGINT, signal_handler)script_directory = os.path.dirname(os.path.abspath(__file__))relative_path = "../config/car_vcu2.dbc"gps_dbc_file = os.path.join(script_directory, relative_path)dbc = cantools.db.load_file(gps_dbc_file)bus = can.interface.Bus(channel='can0', bustype='socketcan')rospy.init_node('pub_vcu1', anonymous=False)print("success")interval = 0.001  # 时间间隔,单位为秒total_time = 5  # 总运行时间,单位为秒Speed_value_threading = MyThread(target=speed_change_brake, args=(interval, total_time))    Speed_value_threading.start()Speed_value_threading.join()result = Speed_value_threading.result# time.sleep(0.01)x_values = list(range(len(result)))  plt.scatter(x_values, result)plt.xlabel('Time')plt.ylabel('y')plt.title('speed 曲线')plt.show()while not is_exit :if flag_wire == 0 :  # 0-wirecontrol发布 1-不发布messages_1[1]['signals']['target_velocity'] = ymsg_recv_from_vcu(dbc, bus)msg_send_to_vcu(messages_1, dbc, bus)time.sleep(0.01)Can_shutdown_threading = threading.Thread(target=can_stop_thread,args=())Can_shutdown_threading.start()Can_shutdown_threading.join()if __name__ == '__main__':main()

到目前为止现在是对线程的写法和运行机理理解最深的时候。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/225242.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 自动化之收发邮件(二)

发邮件之Windows进程监控 文章目录 发邮件之Windows进程监控前言一、基本内容二、基本结构三、库模块四、函数模块1.进程监控2.邮件发送 五、程序运行模块1.获取时间2.用户输入3.进程监控3.1进程启动发邮件3.2进程停止发邮件 总结 前言 上一篇简单写了一下如何进行邮件的收发操…

如何正确理解和使用 Golang 中 nil ?

目录 指针中的 nil 切片中的 nil map 中的 nil 通道中的 nil 函数中的 nil 接口中的 nil 避免 nil 相关问题的最佳实践 小结 在 Golang 中&#xff0c;nil 是一个预定义的标识符&#xff0c;在不同的上下文环境中有不同的含义&#xff0c;但通常表示“无”、“空”或“…

LeetCode 2415. 反转二叉树的奇数层:深度优先搜索(DFS)

【LetMeFly】2415.反转二叉树的奇数层&#xff1a;深度优先搜索(DFS) 力扣题目链接&#xff1a;https://leetcode.cn/problems/reverse-odd-levels-of-binary-tree/ 给你一棵 完美 二叉树的根节点 root &#xff0c;请你反转这棵树中每个 奇数 层的节点值。 例如&#xff0c…

部署LVS的NET模式

实验准备 #负载调度器# 192.168.116.40 #内网 12.0.0.100 #外网 先添加双网卡 #web服务器# 192.168.116.20 #web1 192.168.116.30 #web2 #nfs共享服务# 192.168.116.10 #nfs systemctl stop firewalld setenforce 0 1.nfs共享文件 1…

Axure元件库的介绍以及个人简介和登录界面案例展示

目录 一. 元件介绍 二. 基本元件的使用 2.1 形状元件 2.2 图片元件 2.3 占位符 2.4 文本 2.5 线段元件 2.6 热区文件 三. 表单元件的使用 3.1 文本框 3.2 文本域 3.3 下拉列表 3.4 列表框 3.5 复选框 3.6 单选按钮 四. 菜单与表格元件的使用 4.1 树 4.2 表格…

Cmake基础(1)

什么是cmake 众所周知&#xff0c;对于C/C&#xff0c;不同的IDE的project文件是不同的&#xff0c;VS中叫做vcproject。在linux中make工具叫做makefile&#xff0c;codeblock中叫做cpb。而cmake是一个通用的project组织方式&#xff0c;cmake的项目文件cmakelists.txt可以转成…

持续集成交付CICD:GitLabCI操作Harbor仓库

目录 一、实验 1.GitLabCI操作Harbor仓库 二、问题 1.gitlab-runner连接docker daemon报错 一、实验 1.GitLabCI操作Harbor仓库 &#xff08;1&#xff09;修改GitLabCI共享库代码并提交到mater CI.yaml .pipelineInit:tags:- buildstage: .prevariables:GIT_CHECKOUT: …

Qt图像处理-基于OpenCv的图像二值化处理

本文讲解Qt图像处理-基于OpenCv的图像二值化处理 一、概述 图像二值化原理 图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。 要得到二值化图像,首先要把…

Apache Avro编程快速入门

Maven配置 添加Avro依赖 <dependency><groupId>org.apache.avro</groupId><artifactId>avro</artifactId>

金蝶云星空协同开发环境应用内执行单据类型脚本

文章目录 金蝶云星空协同开发环境应用内执行单据类型脚本业务界面查询单据类型表数据导出数据执行数据库脚本单据类型xml检验是否执行成功检查数据库检查业务数据 金蝶云星空协同开发环境应用内执行单据类型脚本 业务界面 查询单据类型表数据 先使用类型中文在单据类型多语言…

std::iota 函数简单使用

std::iota 是 C 标准库中的一个算法&#xff0c;位于 <numeric> 头文件中。它的作用是用一个连续的范围内的递增序列填充容器。 函数签名如下&#xff1a; template< class ForwardIt, class T > void iota( ForwardIt first, ForwardIt last, T value ); 其中&…

C++使用回调函数的两种方式

一.函数指针 #include <iostream>typedef void (*callback)(int ,int); class MyTest { public:void setCallback(callback cb){m_callback = cb;}void add(int a, int b){m_callback(a, b);}private:callback m_callback; };void onCallback(int a, int b) {std::cout …

[C++]——学习模板

了解模板——初阶 前言&#xff1a;一、模板1.1 什么是模板1.2 模板的概念1.3 模板可以做什么1.4 泛型模板 二、函数模板2.1 函数模板概念和格式2.2 函数模板原理2.3 函数模板实例化2.3.1 隐式实例化2.3.2 显式实例化 2.4 模板参数的匹配原则2.5 函数模板声明定义分离 三、类模…

若依框架springboot——修改前端图片上传样式

简述 使用过若依框架的&#xff0c;一定知道若依前端框架上传图片的样式&#xff0c;是一个正方形加号图片&#xff0c;但是如果你要使用自定义样式呢。 比如将下面这个图进行修改呢 修改后的样式 你可以直接找到element-ui 修改上传图片的组件&#xff0c;也可以加入新的组…

二进制to十六进制

输入小于等于十六位的二进制数据&#xff0c;输出十六进制数据&#xff1b; #include <stdio.h> #include <stdlib.h> #include <math.h>int main(void) {char arr[16] { 0 }; int array[16] { 0 }; int hex[4] { 0 };int i 0; int num 0;scanf("…

AcWing 1250. 格子游戏(并查集)

题目链接 活动 - AcWing本课程系统讲解常用算法与数据结构的应用方式与技巧。https://www.acwing.com/problem/content/1252/ 题解 当两个点已经是在同一个连通块中&#xff0c;再连一条边&#xff0c;就围成一个封闭的圈。一般用x * n y的形式将&#xff08;x, y&#xff0…

CentOS 防火墙管理及使用的redis基本常用命令

文章目录 防火墙管理使用systemctl管理防火墙启动、关闭使用firewalld-cmd配置访问防火墙策略firewalld配置文件修改限制来源IP docker使用 redis 防火墙管理 需要关闭防火墙或者开启对应端口 使用systemctl管理防火墙启动、关闭 启动防火墙&#xff1a; systemctl start fi…

设计模式——桥接模式(结构型)

引言 桥接模式是一种结构型设计模式&#xff0c; 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构&#xff0c; 从而能在开发时分别使用。 问题 抽象&#xff1f; 实现&#xff1f; 听上去挺吓人&#xff1f; 让我们慢慢来&#xff0c; 先考虑一个简单的…

物联网智能仓库解决方案

物联网智能仓库解决方案是一种基于物联网技术的仓库管理系统&#xff0c;通过自动化设备、智能化管理系统和大数据分析等技术&#xff0c;实现仓库的智能化运营和管理。 物联网智能仓库解决方案包括&#xff1a; 仓库设备自动化&#xff1a;通过自动化设备和技术&#xff0c;实…

18--日志(了解)

1、日志 1.1 什么是日志 日志用来记录用户操作、系统运行状态等&#xff0c;是一个系统的重要组成部分。对于一些简单的小程序&#xff0c;可能并不需要在如何记录日志的问题上花费太多精力。但是对于作为基础平台为很多产品提供服务的后端程序&#xff0c;就必须要考虑如何依…