进阶学习-----练习线程思维解决实际问题

线程在IT行业的实际应用

1. 多线程编程

在软件开发中,多线程编程是一种常见的技术,它允许程序同时执行多个任务。以下是多线程编程的一些具体应用:

  • 任务分解:将一个大的任务分解为多个小任务,每个小任务由一个线程执行,这样可以更快地完成整个任务。
  • UI线程与工作线程:在GUI应用程序中,通常会区分UI线程(用于处理用户界面)和工作线程(用于执行耗时操作)。这样,即使工作线程在进行计算或数据处理,UI线程也能保持流畅,响应用户操作。
  • 线程池:为了提高性能和资源利用率,应用程序会使用线程池来管理线程。线程池维护一组线程,这些线程可以重复使用来执行多个任务。

2. 并发处理

在服务器端应用程序中,并发处理至关重要:

  • Web服务器:Web服务器如Apache、Nginx和IIS使用线程(或线程的轻量级版本——协程)来处理并发请求,确保多个用户可以同时访问网站。
  • 数据库服务器:数据库管理系统(如MySQL、PostgreSQL)使用线程来处理多个客户端的查询,保持数据库操作的响应性。

3. 用户界面响应性

在桌面或移动应用程序中:

  • 异步操作:线程允许执行异步操作,例如,在用户上传文件时,可以创建一个线程来处理文件上传,而主线程继续响应用户的其他操作。
  • 事件驱动:在某些框架中,如Java Swing或.NET WinForms,线程用于处理事件循环,确保UI的流畅性和即时响应。

4. 后台任务

后台任务可以包括:

  • 数据同步:在云服务或移动应用中,线程可以用于在后台同步数据,而不会干扰用户当前的工作。
  • 日志记录:应用程序可以使用单独的线程来记录日志,这样即使在主线程繁忙时,日志信息也不会丢失。

5. 并行计算

在科学和工程领域:

  • 大数据处理:在处理大量数据时,可以使用线程将数据分割成块,并在多个处理器核心上并行处理。
  • 数值计算:在数值计算和模拟中,线程可以用来并行化算法,加速计算过程。

6. 任务调度

操作系统中的任务调度器:

  • 优先级调度:线程可以根据优先级被调度,确保重要的任务首先被执行。
  • 时间分片:操作系统通过时间分片技术,在不同的线程之间快速切换,给用户一种多任务同时进行的错觉。

7. 异步操作

在异步编程模式中:

  • 非阻塞I/O:线程可以用来执行非阻塞I/O操作,这样CPU可以在等待I/O完成时执行其他任务。
  • 事件循环:在事件驱动的应用程序中,线程可以用来处理事件循环,管理异步事件的执行。

8. 资源管理

在系统监控和管理中:

  • 性能监控:线程可以用来监控系统的性能指标,如CPU和内存使用情况。
  • 负载均衡:在分布式系统中,线程可以用来实现负载均衡,确保工作负载均匀分布在不同的服务器上。
    通过这些详细的应用场景,我们可以看到线程在IT行业中是如何被广泛使用,以提高效率、优化性能和改善用户体验的。
    在这里插入图片描述

两个没有亲缘关系的进程之间通过消息队列实现简单的聊天,要求在每个进程中创建2个线程, 分别实现消息的发送与接收,同时,一旦一个线程退出,就取消另一个线程。(例如:接收数据的线程收到“bye”后,向发送数据线程发送取消请求后退出, 或发送数据线程发送“bye”数据后,向接收数据的线程发送取消请求后,退出)

在这里插入图片描述

在Linux环境下,可以使用POSIX线程(pthread)和消息队列(POSIX消息队列或System V消息队列)来实现两个没有亲缘关系的进程间的简单聊天。以下是一个使用POSIX线程和POSIX消息队列实现该需求的示例。
首先,需要包含必要的头文件并定义一些全局变量:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <mqueue.h>
#include <unistd.h>
#define QUEUE_NAME "/my_queue"
#define MAX_MSG_SIZE 256
#define MSG_BUFFER_SIZE (MAX_MSG_SIZE + 10)
mqd_t mq;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
volatile int cancel_send = 0;
volatile int cancel_recv = 0;

接下来,定义发送和接收线程的函数:

void *send_msg(void *arg) {char buffer[MSG_BUFFER_SIZE];while (1) {pthread_mutex_lock(&mutex);if (cancel_send) {pthread_mutex_unlock(&mutex);break;}pthread_mutex_unlock(&mutex);printf("Send: ");fgets(buffer, MAX_MSG_SIZE, stdin);buffer[strcspn(buffer, "\n")] = '\0'; // Remove newline characterif (mq_send(mq, buffer, strlen(buffer) + 1, 0) == -1) {perror("mq_send failed");exit(1);}if (strcmp(buffer, "bye") == 0) {pthread_mutex_lock(&mutex);cancel_recv = 1;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);break;}}return NULL;
}
void *recv_msg(void *arg) {char buffer[MSG_BUFFER_SIZE];while (1) {pthread_mutex_lock(&mutex);if (cancel_recv) {pthread_mutex_unlock(&mutex);break;}pthread_mutex_unlock(&mutex);if (mq_receive(mq, buffer, MSG_BUFFER_SIZE, NULL) == -1) {perror("mq_receive failed");exit(1);}printf("Received: %s\n", buffer);if (strcmp(buffer, "bye") == 0) {pthread_mutex_lock(&mutex);cancel_send = 1;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);break;}}return NULL;
}

最后,在main函数中设置消息队列、创建线程,并处理线程的退出:

int main() {struct mq_attr attr;pthread_t send_thread, recv_thread;// Initialize the queue attributesattr.mq_flags = 0;attr.mq_maxmsg = 10;attr.mq_msgsize = MAX_MSG_SIZE;attr.mq_curmsgs = 0;// Create the message queuemq_unlink(QUEUE_NAME);mq = mq_open(QUEUE_NAME, O_CREAT | O_RDWR, 0644, &attr);if (mq == -1) {perror("mq_open failed");exit(1);}// Create send and receive threadspthread_create(&send_thread, NULL, send_msg, NULL);pthread_create(&recv_thread, NULL, recv_msg, NULL);// Wait for threads to finishpthread_join(send_thread, NULL);pthread_join(recv_thread, NULL);// Cleanupmq_close(mq);mq_unlink(QUEUE_NAME);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

注意:以上代码示例没有处理所有可能的错误情况和边缘情况。在实际使用中,应该添加适当的错误处理和资源清理代码。另外,消息队列的名称需要唯一,所以两个进程应该使用不同的队列名称,或者使用某种机制来确保队列名称的唯一性。
编译时需要链接pthread和rt库:

gcc -o chat_program chat_program.c -lpthread -lrt

运行两个实例即可模拟两个进程之间的聊天。需要注意的是,消息队列是System V IPC对象,因此两个进程需要在同一主机上运行。

在这里插入图片描述

创建2个线程,要求一个线程(A)获取文件大小并返回,另一个线程(B)获取文件拥有者用户的权限并返回,主线程等待两个线程的结果数据后,进行结果输出展示。(文件路径由主线程提供)

以下是一个使用C语言和POSIX线程库(pthread)创建两个线程的示例,一个线程获取文件大小,另一个线程获取文件权限。主线程将等待这两个线程完成它们的任务,并输出结果。

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
// 定义结构体用于传递参数和接收结果
typedef struct {const char *path;off_t size;mode_t mode;
} thread_data_t;
// 线程A:获取文件大小
void *get_file_size(void *arg) {thread_data_t *data = (thread_data_t *)arg;struct stat stat_buf;if (stat(data->path, &stat_buf) == 0) {data->size = stat_buf.st_size;} else {perror("stat failed");data->size = -1;}return NULL;
}
// 线程B:获取文件权限
void *get_file_mode(void *arg) {thread_data_t *data = (thread_data_t *)arg;struct stat stat_buf;if (stat(data->path, &stat_buf) == 0) {data->mode = stat_buf.st_mode;} else {perror("stat failed");data->mode = (mode_t)-1;}return NULL;
}
int main(int argc, char *argv[]) {if (argc != 2) {fprintf(stderr, "Usage: %s <file_path>\n", argv[0]);return EXIT_FAILURE;}const char *file_path = argv[1];pthread_t thread_a, thread_b;thread_data_t data;// 初始化结构体data.path = file_path;data.size = 0;data.mode = 0;// 创建线程Aif (pthread_create(&thread_a, NULL, get_file_size, &data) != 0) {perror("pthread_create failed");return EXIT_FAILURE;}// 创建线程Bif (pthread_create(&thread_b, NULL, get_file_mode, &data) != 0) {perror("pthread_create failed");return EXIT_FAILURE;}// 等待线程A完成pthread_join(thread_a, NULL);// 等待线程B完成pthread_join(thread_b, NULL);// 输出结果if (data.size != -1) {printf("File size: %ld bytes\n", data.size);} else {printf("Failed to get file size.\n");}if (data.mode != (mode_t)-1) {printf("File permissions: %lo (octal)\n", (unsigned long)data.mode & 0777);} else {printf("Failed to get file permissions.\n");}return EXIT_SUCCESS;
}

编译这个程序时,确保链接了pthread库:

gcc -o file_info file_info.c -lpthread

运行程序时,需要提供一个文件路径作为参数:

./file_info /path/to/file

请注意,此代码示例假定运行环境支持POSIX线程和相关的系统调用。在不同的操作系统上,获取文件权限和大小的方法可能有所不同。此外,错误处理在这个示例中被简化了,实际应用中可能需要更完善的错误处理逻辑。

在这里插入图片描述

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

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

相关文章

C#基础——泛型

泛型 C# 中的泛型是一种强大的编程特性&#xff0c;它允许你编写类型安全且灵活的代码。泛型允许你定义类、结构体、接口、方法和委托&#xff0c;而不必在编译时指定具体的数据类型。相反&#xff0c;你可以使用类型参数来定义泛型类型或方法&#xff0c;然后在使用时指定具体…

springboot高校实验室安全管理系统-计算机毕业设计源码73839

目 录 摘要 1 绪论 1.1 研究背景 1.2 选题意义 1.3研究方案 1.4论文章节安排 2相关技术介绍 2.1 B/S结构 2.2 Spring Boot框架 2.3 Java语言 2.4 MySQL数据库 3系统分析 3.1 可行性分析 3.2 系统功能性分析 3.3.非功能性分析 3.4 系统用例分析 3.5系统流程分析…

算法板子:最短路问题——包含朴素Dijkstra算法、堆优化版的Dijkstra算法、SPFA算法、Floyd算法

目录 1. 几种算法的用途2. Dijkstra算法——求源点到其他所有点的最短路径(不能处理负边权)&#xff08;1&#xff09;朴素Dijkstra算法——适用于稠密图&#xff08;2&#xff09;堆优化版的Dijkstra算法——适用于稀疏图 4. SPFA算法——求源点到其他所有点的最短路径、判断是…

WordPress原创插件:disable-gutenberg禁用古腾堡编辑器和小工具

WordPress原创插件&#xff1a;disable-gutenberg禁用古腾堡编辑器和小工具 disable-gutenberg插件下载:https://download.csdn.net/download/huayula/89616495

SpringBoot快速学习

目录 SpringBoot配置文件 多环境配置 SpringBoot整合junit SpringBoot整合mybatis 1.在创建时勾选需要的模块 2.定义实体类 3.定义dao接口 4.编写数据库配置 5.使用Druid数据源 SpringBoot 是对 Spring 开发进行简化的。 那我们先来看看SpringMVC开发中的一些必须流…

翻译: 梯度下降 深度学习神经网络如何学习一

在上一节影片里我讲解了神经网络的结构 首先我们来快速回顾一下 在本节影片里&#xff0c;我们有两个目标 首介绍梯度下降的概念 它不仅是神经网络工作的基础 也是很多其他机器学习方法的基础 然后我们会研究一下这个特别的网络是如何工作的 以及这些隐藏的神经元层究竟在寻找什…

使用Openvino部署C++的Yolov5时类别信息混乱问题记录

使用Openvino部署C的Yolov5时类别信息混乱问题记录 简单记录一下。 一、问题描述 问题描述&#xff1a;在使用Yolov5的onnx格式模型进行C的Openvino进行模型部署时&#xff0c;通过读取classes.txt获得类别信息时&#xff0c;出现模型类别混乱&#xff0c;或者说根本就不给图…

如何将avi格式转换为flv格式呢?

FLV是随着FLASH MX的推出发展而来的一种视频格式&#xff0c;目前被众多新一代视频分享网站所采用&#xff0c;是目前增长较快&#xff0c;也较为广泛的视频传播格式。 FLV格式可以轻松导入FLASH播放器中&#xff0c;另外它还能起到保护版权的作用&#xff0c;非常受欢迎。那么…

在优化微信、支付宝小程序用户体验时有哪些关键指标

在优化小程序用户体验时&#xff0c;有几个关键指标需要特别关注&#xff0c;这些指标不仅能够帮助评估当前的用户体验状况&#xff0c;还能为后续的优化工作提供明确的方向。以下是一些关键指标及其解释&#xff1a; 1. 日活跃用户&#xff08;DAU&#xff09; 是指每天使用…

『 Linux 』网络基础

文章目录 协议分层OSI 七层模型TCP/IP 四层(五层)模型网络协议栈与操作系统的联系报文TCP/IP 通讯过程以太网通信的过程以太网的数据碰撞 协议分层 协议分层是计算机网络中奖网络协议进行组织和管理的方法; 通过将网络通信过程分成多个层次,每个层次负责特定的功能从而简化网络…

触屏交互设备的安全风险

现实中的绝大多数电子设备都具有交互性&#xff0c;而现在越来越多的公共场合有布置越来越多的带触屏的交互设备&#xff0c;功能有简单的&#xff0c;有复杂的&#xff0c;布置的场所和应用的场合也各有不同&#xff0c;几乎在任何一个大型公共场合都可以看到这样的设备&#…

【算法 03】雇佣问题

“雇用问题”及其算法优化 在日常生活和工作中&#xff0c;我们经常会遇到需要从多个选项中做出选择的情况&#xff0c;而“雇用问题”正是这样一个典型的例子。在这个问题中&#xff0c;我们不仅要考虑如何高效地找到最佳候选人&#xff0c;还要关注整个过程中的成本。今天&a…

提高工作效率: AWS Gen AI 在几秒钟内总结会议记录

欢迎来到雲闪世界。全面介绍如何利用 AWS Lambda、Bedrock 和 S3 创建总结会议记录的工作流程 免责声明&#xff1a;本文中使用的会议记录纯属虚构&#xff0c;仅用于作为本文说明和教育目的。它并不反映任何实际的对话、事件或个人。任何与实际人物或事件的相似之处纯属巧合。…

为什么网站要使用HTTPS访问

网站使用HTTPS访问的原因有很多&#xff0c;主要可以归纳为以下几个关键点&#xff1a; 1、数据安全性&#xff1a;HTTPS使用SSL/TLS协议对通信过程进行加密&#xff0c;确保信息在传输过程中不被窃取、篡改或冒充。对于涉及敏感信息&#xff08;如个人身份、信用卡号等&#x…

数字人解决方案——音频驱动机器人

音频集成 机器人 标志着 人工智能&#xff08;AI&#xff09;。 想象一下&#xff0c;机器人可以通过视觉和听觉导航并与周围环境互动。音频驱动的机器人使这成为可能&#xff0c;提高了它们更高效、更直观地执行任务的能力。这一发展可能会影响到各个领域&#xff0c;包括家庭…

github技巧和bug解决方法短篇收集

有一些几句话就可以说明白的观点或者解决的的问题&#xff0c;小虎单独收集到这里。 Commits没有算入每天的activity fork的仓库是不算的。 Commits made in a fork will not count toward your contributions. 参考&#xff1a; Contribution activity not shown for github…

鸿蒙HarmonyOS开发:如何使用第三方库,加速应用开发

文章目录 一、如何安装 ohpm-cli二、如何安装三方库1、在 oh-package.json5 文件中声明三方库&#xff0c;以 ohos/crypto-js 为例&#xff1a;2、安装指定名称 pacakge_name 的三方库&#xff0c;执行以下命令&#xff0c;将自动在当前目录下的 oh-package.json5 文件中自动添…

C# 中引用类型的探讨

引用类型的变量不直接包含其数据&#xff1b;它包含对其数据的引用。 如果按值传递引用类型参数&#xff0c;则可能更改属于所引 用对象的数据&#xff0c;例如类成员的值。 但是&#xff0c;不能更改引用本身的值&#xff1b;例如&#xff0c;不能使用相同引用为新对象分配内存…

QuanTide-weekly第1期

本周Po文 这周我们共发表5篇文章。《基于 XGBoost 的组合策略…》等两篇详细讲解了机器学习构建组合策略的框架和常见问题。 文章要点与结论&#xff1a; 通过两阶段式方案实现多因子、多资产的组合策略构建。第一阶段基于XGBoost构建多个多因子单标的模型&#xff0c;第二阶…

electron-updater实现electron全量更新和增量更新——渲染进程交互部分

同学们可以私信我加入学习群&#xff01; 正文开始 前言更新功能所有文章汇总一、监听页面渲染完毕1.1 myApi.handleCheckPcUpdate检查更新1.2myApi.onPcUpdateProgress接收下载信息1.3myApi.onPcDownloaded监听下载完毕事件 二、立即更新三、跳过更新四、打开更新模块总结 前言…