浅谈对线程的理解

一、线程的概念

1、线程的概念

在Python中,想要实现多任务还可以使用多线程来完成。

2、为什么使用多线程?

进程是分配资源的最小单位 , 一旦创建一个进程就会分配一定的资源 , 就像跟两个人聊QQ就需要打开两个QQ软件一样是比较浪费资源的 .

线程是<font color="red">程序执行的最小单位</font> , 实际上进程只负责分配资源 , 而利用这些资源执行程序的是线程 , 也就说进程是线程的容器 , 一个进程中最少有一个线程来负责执行程序 。同时线程自己不拥有系统资源,只需要一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程<font color="red">共享进程所拥有的全部资源</font> 。这就像通过一个QQ软件(一个进程)打开两个窗口(两个线程)跟两个人聊天一样 , 实现多任务的同时也节省了资源。

3、多线程的作用

def func_a():print('任务A')
​
​
def func_b():print('任务B')
​
​
func_a()
func_b()

☆ 单线程执行

☆ 多线程执行

二、多线程完成多任务

1、多线程完成多任务

① 导入线程模块
import threading
​
② 通过线程类创建线程对象
线程对象 = threading.Thread(target=任务名) 
​
② 启动线程执行任务
线程对象.start()
参数名说明
target执行的目标任务名,这里指的是函数名(方法名)
name线程名,一般不用设置
group线程组,目前只能使用None

2、线程创建与启动代码

单线程案例:

import time
​
​
def music():for i in range(3):print('听音乐...')time.sleep(0.2)
​
​
def coding():for i in range(3):print('敲代码...')time.sleep(0.2)
​
​
if __name__ == '__main__':music()coding()

多线程案例:

import time
import threading
​
​
def music():for i in range(3):print('听音乐...')time.sleep(0.2)
​
​
def coding():for i in range(3):print('敲代码...')time.sleep(0.2)
​
​
if __name__ == '__main__':music_thread = threading.Thread(target=music)coding_thread = threading.Thread(target=coding)
​music_thread.start()coding_thread.start()

3、线程执行带有参数的任务

参数名说明
args以元组的方式给执行任务传参
kwargs以字典方式给执行任务传参
import time
import threading
​
​
def music(num):for i in range(num):print('听音乐...')time.sleep(0.2)
​
​
def coding(count):for i in range(count):print('敲代码...')time.sleep(0.2)
​
​
if __name__ == '__main__':music_thread = threading.Thread(target=music, args=(3, ))coding_thread = threading.Thread(target=coding, kwargs={'count': 3})
​music_thread.start()coding_thread.start()

4、主线程和子线程的结束顺序

import time
import threading
​
​
def work():for i in range(10):print('work...')time.sleep(0.2)
​
​
if __name__ == '__main__':# 创建子进程work_thread = threading.Thread(target=work)# 启动线程work_thread.start()
​# 延时1stime.sleep(1)print('主线程执行完毕')

☆ 设置守护线程方式一

import time
import threading
​
​
def work():for i in range(10):print('work...')time.sleep(0.2)
​
​
if __name__ == '__main__':# 创建子线程并设置守护主线程work_thread = threading.Thread(target=work, daemon=True)# 启动线程work_thread.start()
​# 延时1stime.sleep(1)print('主线程执行完毕')

☆ 设置守护线程方式二

import time
import threading
​
​
def work():for i in range(10):print('work...')time.sleep(0.2)
​
​
if __name__ == '__main__':# 创建子线程work_thread = threading.Thread(target=work)# 设置守护主线程work_thread.setDaemon(True)# 启动线程work_thread.start()
​# 延时1stime.sleep(1)print('主线程执行完毕')

5、线程间的执行顺序

for i in range(5):sub_thread = threading.Thread(target=task)sub_thread.start()

思考:当我们在进程中创建了多个线程,其线程之间是如何执行的呢?按顺序执行?一起执行?还是其他的执行方式呢?

答:线程之间的执行是无序的,验证

☆ 获取当前线程信息

# 通过current_thread方法获取线程对象
current_thread = threading.current_thread()
​
# 通过current_thread对象可以知道线程的相关信息,例如被创建的顺序
print(current_thread)

☆ 线程间的执行顺序

import threading
import time
​
def get_info():# 可以暂时先不加,查看效果time.sleep(0.5)current_thread = threading.current_thread()print(current_thread)
​
​
if __name__ == '__main__':# 创建子线程for i in range(10):sub_thread = threading.Thread(target=get_info)sub_thread.start()

总结:线程之间执行是无序的,是由CPU调度决定某个线程先执行的。

6、线程间共享全局变量

☆ 线程间共享全局变量

多个线程都是在同一个进程中 , 多个线程使用的资源都是<font color="red">同一个进程中的资源</font> ,因此多线程间是共享全局变量

示例代码:

import threading
import time
​
​
my_list = []
​
​
def write_data():for i in range(3):print('add:', i)my_list.append(i)print(my_list)
​
​
def read_data():print('read:', my_list)
​
​
if __name__ == '__main__':write_thread = threading.Thread(target=write_data)read_thread = threading.Thread(target=read_data)
​write_thread.start()time.sleep(1)read_thread.start()

7、总结:进程和线程对比

☆ 关系对比

① 线程是依附在进程里面的,没有进程就没有线程。

② 一个进程默认提供一条线程,进程可以创建多个线程。

☆ 区别对比

① 进程之间不共享全局变量

② 线程之间共享全局变量

③ 创建进程的资源开销要比创建线程的资源开销要大

④ 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位

☆ 优缺点对比

① 进程优缺点:

优点:可以用多核

缺点:资源开销大

② 线程优缺点

优点:资源开销小

缺点:不能使用多核

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

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

相关文章

DP:子数组模型

一、最大子数组和 . - 力扣&#xff08;LeetCode&#xff09; 二、环形子数组的最大和 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int maxSubarraySumCircular(vector<int>& nums) {//动态规划思想解决 //环形数组问题&#xff0c;尝试转…

01-Git 快速入门

https://learngitbranching.js.org/?localezh_CN在线练习git 1. Git 安装好Git以后, 先检查是否已经绑定了用户名和邮箱 git config --list再检查C:\Users\xxx.ssh 下是否存在 id_rsa.pub , 存在的话复制其内容到 GitHub 的 SSH KEY 中 没有这一步, PUSH操作的时候会报错:…

土壤墒情监测系统:洞察土壤水分奥秘

TH-TS400土壤墒情监测系统&#xff0c;作为现代农业科技的重要组成部分&#xff0c;已经成为农业生产过程中不可或缺的一环。该系统通过先进的传感器技术和数据处理能力&#xff0c;能够实时监测土壤的水分状况&#xff0c;为农业生产提供精准、可靠的数据支持。本文将从系统构…

存储设备与网络监控运维实践

随着企业数据量的不断增长和网络架构的日益复杂&#xff0c;存储设备和网络设施的稳定运行变得至关重要。为了确保这些关键组件的性能和可用性&#xff0c;实施全面的监控策略是运维团队的首要任务。本文旨在为运维团队提供存储设备监控、网络流量分析以及网络配置管理方面的参…

如何在debian12.5上安装snap和docker

在Debian 12.5上安装Snap和Docker的步骤如下&#xff1a; 1. 更新系统包列表&#xff1a; sudo apt update sudo apt upgrade 2. 安装 Snap&#xff1a; Debian 12.5 默认已经启用了 Snap 支持&#xff0c;所以你可以直接通过 apt 来安装 Snap。 sudo apt install snapd …

算法打卡day29

今日任务&#xff1a; 1&#xff09;1005.K次取反后最大化的数组和 2&#xff09;134.加油站 3&#xff09;135.分发糖果 1005.K次取反后最大化的数组和 题目链接&#xff1a;1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 给定一个整数数组 A&…

Java Web-分层解耦

三层架构 当我们所有代码都写在一起时&#xff0c;代码的复用性差&#xff0c;并且难以维护。就像我们要修改一下服务端获取数据的方式&#xff0c;从文本文档获取改为到数据库中获取&#xff0c;就难以修改&#xff0c;而使用三层架构能很好的解决这个问题。 controller: 控…

MySql数据库从0-1学习-第二天DML和DQL学习

DML 对数据库表中的数据进行增删改操作 Insert 语法 //指定字段添加数据 insert into 表名(字段名1,字段名2) values (值1,值2);//全部字段添加数据: insert into 表名 values(值1,值2...);//批量添加数据(指定字段) insert into 表名(字段名1,字段名2) values(值1,值2),(值1,…

HJ61 放苹果(递归,苹果多的情况+盘子多的情况)

当苹果数 < 盘子数&#xff0c;有空盘&#xff0c;则忽略一个盘子&#xff0c;在n-1个放苹果&#xff0c;一直递推到n1&#xff0c;有一种摆法苹果数 > 盘子数&#xff0c;可以看作没有空盘。则可以选择忽略一个盘子&#xff0c;如上边做法。还可以选择每个盘子放一个苹果…

react ant design 通过函数弹出 modal窗口

在React Ant Design中&#xff0c;可以通过调用Modal组件的方法来动态弹出和关闭Modal窗口。具体步骤如下&#xff1a; 1、首先&#xff0c;在组件中引入Modal组件&#xff1a; import { Modal } from antd;2、在组件中定义一个函数来弹出Modal窗口&#xff1a; const showM…

GlusterFS分布式存储

目录 前言 一、GlusterFS分布式存储概述 1、GFS概念 2、GFS特点 3、GFS术语 4、GFS构成 5、GFS工作流程 6、后端存储如何定位文件 7、GlusterFs的卷类型 7.1 Distributed Volume&#xff08;分布式卷&#xff09; 7.2 Striped Volume&#xff08;条带卷&#xff09…

Pgsql怎样找到表中某个字段值重复的记录并删除冗余记录,只保留一条

背景 今天发现某个黄页爬取的数据有部分重复了&#xff0c;原本我用的公司详情页的url进行md5来作为主键做upsert入&#xff0c;但后面在核验数据时发现有些详情url虽是同一间公司的&#xff0c;但路由上有细微差别导致写入了重复的公司数据&#xff0c;所以要想办法清理掉重复…

线性变换在人工智能领域的深度实践与应用探索

线性变换&#xff0c;作为数学中的一种基本工具&#xff0c;在人工智能领域中发挥着举足轻重的作用。其强大的表示能力和灵活的运算特性使得线性变换成为机器学习、深度学习等多个子领域的核心组成部分。本文将详细探讨线性变换在人工智能领域中的实践应用&#xff0c;旨在揭示…

redis分布式锁介绍及代码示例

Redis 分布式锁是一种利用 Redis 实现的分布式系统中的锁机制&#xff0c;用于在分布式环境下控制多个客户端对共享资源的访问。它通过 Redis 的原子性操作来确保在分布式系统中的不同节点上&#xff0c;同一时刻只有一个客户端能够获取到锁&#xff0c;从而保证了对共享资源的…

自动化测试selenium

目录 什么是自动化测试 什么是selenium selenium工作原理 selenium环境搭建 1.查看chrome浏览器版本 2.下载chrome浏览器驱动 3.配置系统环境变量PATH 4.验证环境是否搭建成功 selenium相关API 1.定位元素 CSS选择器定位 xpath定位元素 标签定位元素 2.操作测试对…

2024年华为OD机试真题-孙悟空吃蟠桃-Python-OD统一考试(C卷)

题目描述: 孙悟空爱吃蟠桃,有一天趁着蟠桃园守卫不在来偷吃。已知蟠桃园有N颗桃树,每颗树上都有桃子,守卫将在H小时后回来。 孙悟空可以决定他吃蟠桃的速度K(个/小时),每个小时选一颗桃树,并从树上吃掉K个,如果树上的桃子少于K个,则全部吃掉,并且这一小时剩余的时间…

novnc本地文件读取和写入权限

在使用NoVNC&#xff08;一种基于Web的VNC客户端&#xff09;时&#xff0c;出于安全考虑&#xff0c;通常不允许直接从客户端访问或修改服务器上的文件系统。如果你需要在NoVNC中实现文件的读写&#xff0c;你可能需要使用一些特殊的配置或者服务器端的支持。 例如&#xff0…

浏览器工作原理与实践--渐进式网页应用(PWA):它究竟解决了Web应用的哪些问题

在专栏开篇词中&#xff0c;我们提到过浏览器的三大进化路线&#xff1a; 第一个是应用程序Web化&#xff1b; 第二个是Web应用移动化&#xff1b; 第三个是Web操作系统化&#xff1b; 其中&#xff0c;第二个Web应用移动化是Google梦寐以求而又一直在发力的一件事&#xf…

【免费SSL】免费一年的SSL证书

一、SSL证书行业政策 目前市面上绝大多数的免费SSL证书有效期都在3个月左右&#xff0c;而不是一年。例如&#xff0c;腾讯云在2024年4月后不再提供有效期为一年的免费证书&#xff0c;改为提供有效期为3个月的免费证书。同样&#xff0c;阿里云在2023年11月后也不再提供有效期…

javaScript常见对象方法总结

1&#xff0c;object.assign() 用于合并对象的属性。它可以将一个或多个源对象的属性复制到目标对象中&#xff0c;实现属性的合并。 语法 Object.assign(target, ...sources); 1,target&#xff1a;目标对象&#xff0c;将属性复制到该对象中。 2,sources&#xff1a;一个…