当前位置: 首页 > news >正文

python从入门到精通(十九):python的多线程详细使用

python的多线程详细使用

  • 1.什么是线程
  • 2.线程的作用
  • 3.导入线程
    • 4.创建线程
      • 启动线程
      • 线程阻塞
      • 线程的方法
    • 守护线程
    • 线程阻塞
      • 2个都是守护线程
      • 1个是守护线程
    • 线程间通信

1.什么是线程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

2.线程的作用

Python中的程序默认是只有一个主线程的,也就是说,执行程序的时候,你写的代码都是串行执行的,CPU利用率可能并没有得到很好的利用,还有很多的空闲,而这个时候利用多线程,多线程是指同时使用多个线程执行代码,以实现并发执行任务的目的,CPU利用率将会大大提升,程序速度也就能大大增快

3.导入线程

多线程开发推荐使用 threading 模块

from threading import Thread

4.创建线程

调用threading.Thread类

threading.Thread(target=None, name=None, args=(), kwargs={})
# target 指要创建的线程的方法名,name 指给此线程命名,命名后可以调用 threading.current_thread().name 方法输出该线程的名字
# args/kwargs 指 target 指向的方法需要传递的参数,必须是元组形式,如果只有一个参数,需要以添加逗号

实例化线程

# method 为线程要执行的具体方法
thread01 = Thread(target=method)  #method要使用线程的函数名称

实现两条线程

thread02 = Thread(target=method)

实现多个线程依次类推

启动线程

thread01.start()
thread01.start()

线程阻塞

等待所有线程执行完成再进行下一步操作

thread01.join()
thread02.join()
# 等待线程执行完成

线程的方法

方法描述
threading.current_thread()返回当前线程的信息
threading.enumerate()返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程
threading.active_count()返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
import time
import threading
from threading import Thread
def task():num = 0for i in range(100):num *= iresult.append(num)thread01 = Thread(target=task)
thread02 = Thread(target=task)
if __name__ == "__main__":thread01.start()thread02.start()print("正在运行的线程数量", threading.active_count())print("将当前所有线程的具体信息展示出来", threading.enumerate())print("返回当前线程的信息", threading.current_thread())
 2
将当前所有线程的具体信息展示出来 [<_MainThread(MainThread, started 12752)>]
返回当前线程的信息 <_MainThread(MainThread, started 12752)>

守护线程

Python在进程启动起来后,会自动创建一个主线程,主线程默认会等待所有线程执行完成之后再退出,但是如果我们设置了守护线程,主线程任务一旦完成,所有子线程将会和主线程一起结束,即使子线程没有执行完也会退出。

方法一:设置守护线程是创建子线程对象时,以daemon参数的形式指定

thread01 = Thread(target=task,name="t1",daemon=True)

方法二:通过setDaemon(True)的形式进行设置

thread01.setDaemon(True)
在这里插入代码片

线程阻塞

假如说我们不希望主线程完成直接退出而不等待其他线程的话,我们可以为主线程设置阻塞,并设计好阻塞时间,以等待其他线程执行完毕。用join()方法使主线程陷入阻塞,是实现线程同步的一种方式。参数timeout可以用来设置主线程陷入阻塞的时间,

2个都是守护线程

def task(num):print('线程名称:', threading.current_thread().name, '参数:', num, '开始时间:',time.strftime('%Y-%m-%d %H:%M:%S'))thread01 = Thread(target=task, name="t1", daemon=True, args=(6,))
thread02 = Thread(target=task, name="t2", daemon=True, args=(10,))
if __name__ == "__main__":print('主线程开始时间:', time.strftime('%Y-%m-%d %H:%M:%S'))thread01.start()thread02.start()thread01.join(timeout=3)  # 主线程等待3秒 等待线程1执行完thread02.join(timeout=3)  # 主线程阻塞3秒 等待线程2执行完 共阻塞6秒 全部执行完毕print("正在运行的线程数量", threading.active_count())print("将当前所有线程的具体信息展示出来", threading.enumerate())print("返回当前线程的信息", threading.current_thread())

1个是守护线程

一个子线程设为非守护线程,另一个子线程设为守护线程,主线程等待3秒后结束,看看输出的情况。

def task(num):for i in range(num):print('线程名称:', threading.current_thread().name, '参数:', num, '开始时间:',time.strftime('%Y-%m-%d %H:%M:%S'))time.sleep(2)thread01 = Thread(target=task, name="t1",daemon=True, args=(1,))thread02 = Thread(target=task, name="t2",args=(100,))
if __name__ == "__main__":print('主线程开始时间:', time.strftime('%Y-%m-%d %H:%M:%S'))thread01.start()thread02.start()# 主线程等待3秒time.sleep(3)print('{} Runing'.format(threading.current_thread().name))print("正在运行的线程数量", threading.active_count())print("将当前所有线程的具体信息展示出来", threading.enumerate())print("返回当前线程的信息", threading.current_thread())
主线程开始时间: 2024-02-12 16:07:05
线程名称: t1 参数: 1 开始时间: 2024-02-12 16:07:05
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:05
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:07
MainThread Runing
正在运行的线程数量 2
将当前所有线程的具体信息展示出来 [<_MainThread(MainThread, started 9624)>, <Thread(t2, started 7112)>]
返回当前线程的信息 <_MainThread(MainThread, started 9624)>
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:09
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:11
线程名称: t2 参数: 100 开始时间: 2024-02-12 16:07:13

守护进程已经执行完了,但是非守护进程还在执行,程序也就还在执行,一旦非守护进程结束,会随主线程全部结束。

线程间通信

线程之间共享同一块内存。子线程虽然可以通过指定target来执行一个函数,但是这个函数的返回值是没有办法直接传回主线程的。我们使用多线程一般是用于并行执行一些其他任务,因此获取子线程的执行结果十分有必要。

相关文章:

  • Spark编程实验六:Spark机器学习库MLlib编程
  • CI/CD到底是啥?持续集成/持续部署概念解释
  • HTTP网络通信协议基础
  • 【算法训练营】等式,道路升级(c++,python实现)
  • 高斯模糊滤镜
  • AJAX——URL查询参数
  • AI少女/HS2甜心选择2 仿剑三剑灵人物卡全合集打包
  • Unity学习笔记(零基础到就业)|Chapter02:C#基础
  • TCP高频知识点
  • 物联网中基于WIFI的室内温度检测系统设计
  • 【React】如何使antd禁用状态的表单输入组件响应点击事件?
  • C++三剑客之std::optional(一) : 使用详解
  • 常见范数介绍
  • css浮动
  • C/C++模板初阶
  • [deviceone开发]-do_Webview的基本示例
  • 0基础学习移动端适配
  • 3.7、@ResponseBody 和 @RestController
  • C++11: atomic 头文件
  • Druid 在有赞的实践
  • java8 Stream Pipelines 浅析
  • JavaScript设计模式之工厂模式
  • jdbc就是这么简单
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • rc-form之最单纯情况
  • Solarized Scheme
  • spring boot下thymeleaf全局静态变量配置
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 如何优雅地使用 Sublime Text
  • 少走弯路,给Java 1~5 年程序员的建议
  • 深入浏览器事件循环的本质
  • 深入浅出webpack学习(1)--核心概念
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 异步
  • 怎么把视频里的音乐提取出来
  • ​如何在iOS手机上查看应用日志
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #Lua:Lua调用C++生成的DLL库
  • #数学建模# 线性规划问题的Matlab求解
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (175)FPGA门控时钟技术
  • (5)STL算法之复制
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (独孤九剑)--文件系统
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (原)Matlab的svmtrain和svmclassify
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)memcache、redis缓存
  • (转)平衡树