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

[Python学习日记-91] 并发编程之多线程 —— threading 模块、开启线程的方式、线程相关的其他方法

[Python学习日记-91] 并发编程之多线程 —— threading 模块、开启线程的方式、线程相关的其他方法

简介

threading 模块

开启线程的方式

一、方式一:把可调用对象(函数)传递给 Thread 类

二、方式二:继承 Thread 类,并重写其 run 方法

三、同一线程下开启多个线程与多个子进程的区别

1、开进程的开销远大于开线程,所以开线程的速度会比开进程快

2、同一进程内的多个线程共享该进程的地址空间

3、查看 PID

四、练习

1、多线程并发的 Socket 通信

2、多线程并行大写转换

线程相关的其他方法

简介

        在前面的线程理论的介绍当中我们已经介绍了线程的概念、线程与进程的区别、经典的线程模型、POSIX线程和线程的实现理论,这些都是比较偏向于理论的。本篇我们将进入实际敲代码的阶段,看看在 Python 当中应该如何创建线程等,以及使用进程时有什么需要注意的地方。

threading 模块

        threading 模块能够让你创建和管控线程,进而实现多任务并行处理。其与 multiprocessing 模块的接口基本一致,这是因为 multiprocessing 模块的完全模仿了 threading 模块的接口,二者在使用层面有着很大的相似性,我们可以回顾一下对 multiprocessing 模块的介绍。threading 模块也提供了 Process、Pool、Queue、Pipe、Lock 等组件。

  • Thread 类:用于创建和管理线程,可以通过创建该类的实例来启动一个新的线程;
  • Lock 类(互斥锁):提供了一个简单的锁对象,用于在多个线程之间同步访问共享资源,解决数据不一致的问题;
  • RLock 类(可重入锁):允许同一线程多次获取锁(避免死锁),与 Lock 不同的是 RLock 可以被同一线程重复获取;
  • Semaphore 类:指定同一时间的信号量,用于控制同时访问资源的线程数量;
  • Event 类:线程间的简单通信,通过标志位(set()/clear())控制阻塞;
  • Condition 类:高级同步原语,允许线程在特定条件下等待或唤醒其他线程;
  • Timer 类:定时器,用于延迟执行指定函数;
  • Barrier 类:让多个线程在某个点同步(全部到达后继续执行);
  • Local 类:线程局部存储,为每个线程创建独立的变量副本;

官方链接:https://docs.python.org/3/library/threading.html

开启线程的方式

一、方式一:把可调用对象(函数)传递给 Thread 类

import time
import random
from threading import Threaddef piao(name):print('%s doing' % name)time.sleep(random.randrange(1, 5))print('%s do end' % name)if __name__ == '__main__':t1 = Thread(target=piao, args=('jove',))t1.start()print('主线程')

代码输出如下:

二、方式二:继承 Thread 类,并重写其 run 方法

import time
import random
from threading import Threadclass MyThread(Thread):def __init__(self, name):super().__init__()self.name = namedef run(self):print('%s doing' % self.name)time.sleep(random.randrange(1, 5))print('%s do end' % self.name)if __name__ == '__main__':t1 = MyThread('jove')t1.start()print('主线程')

代码输出如下:

三、同一线程下开启多个线程与多个子进程的区别

1、开进程的开销远大于开线程,所以开线程的速度会比开进程快

import time
from threading import Thread
from multiprocessing import Processdef piao(name):print('%s doing' % name)time.sleep(2)print('%s do end' % name)if __name__ == '__main__':# 开启进程p1 = Process(target=piao, args=('jove',))p1.start()# 开启线程t1 = Thread(target=piao, args=('kerry',))t1.start()print('主线程')

代码输出如下:

2、同一进程内的多个线程共享该进程的地址空间

进程的效果

from threading import Thread
from multiprocessing import Processn = 100
def task():global nn = 0if __name__ == '__main__':# 在主进程下开启子进程print('子进程',n)p1 = Process(target=task,)p1.start()p1.join()print('主线程',n)

代码输出如下: 

线程的效果

from threading import Thread
from multiprocessing import Processn = 100
def task():global nn = 0if __name__ == '__main__':# 在主进程下开启线程print('线程', n)t1 = Thread(target=task,)t1.start()t1.join()print('主线程',n)

代码输出如下:

3、查看 PID

进程的 PID

from threading import Thread
from multiprocessing import Process,current_process
import osdef task():# print(current_process().pid)print('子进程PID:%s  父进程的PID:%s' % (os.getpid(),os.getppid()))if __name__ == '__main__':# 开多个进程,每个进程都有不同的 PIDp1 = Process(target=task,)p2 = Process(target=task, )p1.start()p2.start()# print('主线程',current_process().pid)print('主线程',os.getpid())

代码输出如下:

线程的 PID

from threading import Thread
import osdef task():# print(current_process().pid)print('子线程PID:%s' % os.getpid())if __name__ == '__main__':# 多个子线程的 PID 都和所在主进程的 PID 一样t1 = Thread(target=task, )t2 = Thread(target=task, )t1.start()t2.start()print('主进程', os.getpid())

代码输出如下: 

四、练习

1、多线程并发的 Socket 通信

        这个之前在网络编程基础实战 —— 多用户 FTP 项目的多线程版就写过了,这里就不再重复了,有兴趣的可以去翻看一下。

2、多线程并行大写转换

        三个任务,一个接收用户输入,一个将用户输入的内容格式化成大写,一个将格式化后的结果存入文件。

from threading import Thread
msg_l=[]
format_l=[]
def talk():while True:msg=input('>>: ').strip()if not msg:continuemsg_l.append(msg)def format_msg():while True:if msg_l:res=msg_l.pop()format_l.append(res.upper())def save():while True:if format_l:with open('threading_db.txt','a',encoding='utf-8') as f:res=format_l.pop()f.write('%s\n' %res)if __name__ == '__main__':t1=Thread(target=talk)t2=Thread(target=format_msg)t3=Thread(target=save)t1.start()t2.start()t3.start()

代码输出如下:

线程相关的其他方法

Thread 类实例对象的方法

isAlive():返回线程是否活动的,当前(Python 3.12.4)已变为 is_alive()

getName():返回线程名,当前(Python 3.12.4)该方法已被弃用改用为 name 属性

setName():设置线程名,当前(Python 3.12.4)该方法已被弃用,只需要直接对 name 属性赋值即可

threading 模块提供的一些方法

threading.current_thread():返回当前的线程变量

threading.enumerate():返回一个包含正在运行的线程的 list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程

threading.active_count():返回正在运行的线程数量,与 len(threading.enumerate()) 有相同的结果

演示代码如下: 

from threading import Thread,current_thread,active_count,enumerate
import timedef task():print('%s is running\n' % current_thread().name)  # 原 getName()time.sleep(2)print('%s is done\n' % current_thread().name)  # 获取当前线程名 current_thread()获取当前线程if __name__ == '__main__':t = Thread(target=task,name='子线程1')t.start()t.name = '儿子线程1'  # 该线程名,原 setName()print(current_thread()) # 主线程print(enumerate())  # 把当前活跃的线程以列表的形式列出来,连同主线程一共有两个运行线程print(active_count())  # 查看目前存活的线程数t.join()    # 主线程等待子线程结束print(t.name)current_thread().name = '主线程/主进程'  # 修改主线程名print(t.is_alive()) # 原 isAlive()print('主线程/主进程',current_thread().name)

代码输出如下:

http://www.xdnf.cn/news/12490.html

相关文章:

  • 腾讯加持,销售易 CRM 优势几何?
  • 本机无法远程别的计算机的方法
  • 自制喜悦字贴
  • QILSTE 精巧电子元件H4-108FO/5M解析
  • 观测云OaC能力升级,通过Terraform实现配置闭环
  • MySQL基础(一)介绍、下载及安装
  • w384药品管理系统的设计与实现
  • MySQL基础(三)DQL(Data Query Language,数据查询语言)
  • 【第一章:人工智能基础】01.Python基础及常用工具包-(1)Python语法与基础数据类型
  • 开源音乐播放器 MusicFree 项目介绍:自由、纯粹、高度自定义的听歌体验
  • 谷歌云代理商 | 游戏行业专属方案:谷歌云实时多人游戏服务器架构
  • STM32实战: CAN总线数据记录仪设计方案
  • 利用ProtoBuf 实现网络版通讯录
  • Vue基础(14)_列表过滤、列表排序
  • arcpy与扩展模块
  • 灵感枯竭?ai写小说生成器来帮忙
  • 深入理解数字音频:采样率、位深与量化
  • nuScenes 数据集及同类型自动驾驶数据集介绍
  • vue3 按钮级别权限控制
  • 车型库查询接口如何用Java进行调用?
  • 【机械视觉】Halcon—【十、实例—木头检测_充电宝检测_豆子检测】
  • python打卡44天
  • Linux 下的COW机制(copy-on-write)
  • python八股文算法:三数之和
  • 前端~三维地图(cesium)地图遮罩蒙层
  • 货运车辆在高速公路上发生故障,应如何设置警示标志?
  • 山洪径流过程及洪水淹没数值模拟
  • JDK21 虚拟线程原理剖析与性能深度解析
  • 力扣面试150题--克隆图
  • 2025年服装收银系统推荐:助力服装商家高效经营