XX学Python·进程与线程
多任务编程-进程
-
多任务执行方式
-
并发:在一段时间内交替去执行任务
-
并行:多核cpu每个cpu执行一个任务。注:任务>cpu时,每个cpu并发执行多个任务
-
-
进程:计算机中的程序关于某数据集合上的一次运行活动,是操作系统资源(内存)分配的基本单位。一个程序运行后至少有一个进程,一个进程至少有一个线程。
-
一个进程就开辟一块内存空间,多线程是利用一个内存空间
-
多进程的基本使用:
# def login(): # print('登录') # # # if __name__ == '__main__': # login() # login() # # 上面相当于在一个进程里面执行了多次方法。同一内存块里。 # 使用多进程的形式完成多次调用。相当于把程序复制后在不同的内存空间单独执行。 import multiprocessing # 导入多进程模块 def login(): print('登录') # p1 = multiprocessing.Process(target=login()) # p1.start() # 上面没放入if __name里运行报错,系统认为原有方法要执行一次,相当于重复运行。 if __name__ == '__main__': # 多进程要放入if __name__里 # Process括号里参数: # group=None 指定分组,推荐使用默认None, # target=None 指定要调用的函数名,常用 # name=None 指定进程名称, # args=()元组传参注意一个元素('xx',), kwargs={}给函数传递参数 # daemon=None 指定守护进程 # Process是一个类,注意不能用小写process # Process中target指定的是子进程要执行的任务,所以切记任务后面不要添加括号 p1 = multiprocessing.Process(target=login) # 创建了一个进程 p2 = multiprocessing.Process(target=login) # 相当于创建了一个实例对象 p1.start() # 运行进程指定对应函数业务逻辑 p2.start() # 使用start运行
-
进程编号:子进程是由主进程创建出来的。
-
获取当前进程编号:os.getpid()
-
获取当前父进程编号:os.getppid()
-
import multiprocessing import os def login(name, password): print('名字:', name) print('密码:', password) print('登录') # 获取当前进程名称 print('进程名称:', multiprocessing.current_process().name) # 获取当前进程编号,这里获取就是子进程 print('子进程:', os.getpid()) # 获取主进程编号,pid前面加了一个p,父进程 print('子进程的父进程编号:', os.getppid()) if __name__ == '__main__': # group=None 指定分组,推荐使用默认None # target=None 指定要调用的函数名 # name=None 指定进程名称 # args=(), kwargs={}给函数传递参数, # daemon=None 指定守护进程 p1 = multiprocessing.Process(target=login, args=('Python', 123456), name='p1') p2 = multiprocessing.Process(target=login, kwargs={'name': 'xx', 'password': 123456}, name='p2') p3 = multiprocessing.Process(target=login, kwargs={'name': 'lsl', 'password': 123456}, name='p3') p1.start() p1.join() p2.start() p2.join() p3.start() p3.join() # 如果需要进程按照循序执行,需要用进程等待join方法,但一般不用。 # 不用join,顺序就不一定,是cpu根据他的调用算法随机执行 # 获取当前进程编号,使用os模块。这里获取的主进程编号。 print('主进程:', os.getpid())
-
进程注意点
-
进程间不共享全局变量
-
正常情况下主进程会等待子进程结束后在退出主进程
-
import multiprocessing # 不共享全局变量 data_list = [] def write_data(): # 往全局列表中写入数据 for i in range(0, 50): print(i) data_list.append(i) print('write_data方法写入的数据为:', data_list) def read_data(): print('read_data方法读取的数据为:', data_list) if __name__ == '__main__': # 创建多进程分别调用两个读写方法,验证全局变量是否共享数据 p1 = multiprocessing.Process(target=write_data, daemon=True) p2 = multiprocessing.Process(target=read_data) p1.start() p2.start() # 正常情况下主进程会等待子进程结束后在退出主进程 # 需求主进程结束后就结束子进程,不再进行等待 # 两种形式实现 第一种设置守护进程参数daemon=True或 子进程对象.daemon=True # 第二种 主动关闭子进程 p2.terminate() print('主进程读取的数据:', data_list)
多任务编程-线程
-
线程:是操作系统运算调度的最小单位。被包含在进程之中,是进程实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
-
线程的基本使用
# 导入线程模块 import threading def func(data): print('线程使用') print(f'参数数据:{data}') # 获取当前执行线程的名称 print('线程名称:', threading.current_thread().name) if __name__ == '__main__': # 创建线程 # group = None, 使用默认 # target = None, 指定函数方法 # name = None, 指定线程名称 # args = (), kwargs = None, 传递参数 # daemon = None 设置守护线程 t1 = threading.Thread(target=func, args=('python',), name='t1') t2 = threading.Thread(target=func, kwargs={'data': 'itcast'}, name='t2') # 启动运行线程 t1.start() t2.start()
-
线程注意点
-
线程执行是无序的,根据cpu随机调度
-
主线程会等待子线程结束后在结束:指定守护线程或线程对象.setDaemon(True),当主线程结束后自动结束子线程
-
线程间共享全局变量。但要注意无序执行导致的数据错乱,使用join等待
-
import threading data = 0 def func1(): global data for i in range(0, 1000000): data += 1 print(f'函数1的累加结果:{data}') def func2(): global data for i in range(0, 1000000): data += 1 print(f'函数2的累加结果:{data}') if __name__ == '__main__': # 创建两个线程进程累加 t1 = threading.Thread(target=func1) t2 = threading.Thread(target=func2) # 通过join的形式让函数顺序执行 t1.start() t1.join() t2.start() t2.join() print(f'主线程的结果展示:{data}')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」