栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python中 (Threading/multiprocessing)//并发、并行、单进程、多进程、单线程、多线程//

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python中 (Threading/multiprocessing)//并发、并行、单进程、多进程、单线程、多线程//

python中 (Threading/multiprocessing)//并发、并行、单进程、多进程、单线程、多线程// ___[ 详解 ]____
  • 简单的概念术语
    • 并发
    • 并行
    • 单进程
    • 多进程
    • 单线程 / 多线程
  • multiprocessing模块-———基于进程的并行
    • (1)multiprocessing.Process—参数args(,)kwarg{}—语法
    • (2)获取进程的编号
    • (3) 守护进程:
  • Threading模块——
    • (1) threading——常用参数
    • (2)join()————子线程终止的使用。
    • (3)Lock()——子线程锁的运用。

简单的概念术语 并发

单核 多个任务交替进行完成;
简单理解:
一个人(相当于一个核)做饭 ,你得买菜,煮饭,切菜,炒菜 。
一个人完成整个做饭的过程。
就是为了执行完成多个任务。

并行

多个CPU同时执行任务完成;
简单理解:
做饭的时候有多个人来帮你一起,有人洗菜,有人煮饭,有人切菜,有人炒菜;提高做饭的效率
多个CPU同时协助执行提高效率。

单进程

进程的概念:一个正在打开运行中的程序就称为进程,
通俗理解就相当于QQ,微信运行起来的程序
打开后就变成了一个各自独立的进程,任务管理器中可查看,
一个运行起来的程序至少有一个进程。

多进程

多个运行起来的程序就是一个多进程;
简单理解 :
在家想做饭吃牛肉和螃蟹,为了提高效率叫表弟去买螃蟹,表妹去买虾,自己则在家里煮饭,来提高想吃饭的效率。
多任务同时执行充分调用CPU资源来提高效率。
主进程和子进程同时执行。

单线程 / 多线程

线程是程序执行的最小单位,线程是依附于进程中执行的,一个程序默认最少都会有一个线程。
简单理解:
你有一个想接满水的大盆,(线程好比水龙头)你开一个水龙头接水,和开多个水龙头接水,效率远远不一样。
就像打开QQ 后想和多个人聊天,打开多个聊天窗口(多个线程)的聊天一样,实现多任务的同时节省了资源。

multiprocessing模块-———基于进程的并行

进程的创建步骤
(1)导入进程包

#先导入包
import multiprocessing

(2)通过进程类创建进程对象
进程对象 = multiprocessing.Process()
(3)启动进程执行任务
进程对象.start()
通过进程类创建进程对象
进程对象 =multiprocessing.Process(target=任务名)
任务名就是接下来的函数名 注意的是任务名不要(),不然就是调用,这里是为了多进程的索引。

参数名说明
target执行目标的名
name进程名,默认系统设置,可手动指定
group进程组,目前None
# 唱歌
def sing():
    for i in range(3):
        print('小明', end='')
        print('唱歌----')
        time.sleep(0.5)
# 跳舞
def dance():
    for i in range(3):
        print('小花', end='')
        print('跳舞----')
        time.sleep(0.5)
        
if __name__ == '__main__':
	start_time= time.time()  #计时
    dance()
    sing()
    end_time = time.time()
    all_time = end_time-start_time
    print(f'时间:{all_time}')

——可以看到函数的调用就是单个执行——总时间
想在快点 执行完成 。
我们再更改一下唱跳一起执行:

	if __name__ == '__main__':
	
	start_time= time.time()  #开始计时
    dance_process = multiprocessing.Process(target=dance,)
    sing_process = multiprocessing.Process(target=sing)

    dance_process.start()  #启动子进程
    sing_process.start()
    end_time = time.time()
    all_time = end_time-start_time
    print(f'时间:{all_time}')
    


——从时间上看快了不止快了 ‘‘亿’’ 点点——

(1)multiprocessing.Process—参数args(,)kwarg{}—语法
arg(,)元组传递中间得有逗号以保证是一个元组 
元组传递参数是按照 位置传参,不然报错
kwargs{}是字典传参
按照关键字传参,传入的参数名和函数接受的名字得一样  否则报错
#跳舞
def dance(num,name):   		#kwargs()关键字传参
    for i in range(num):
        print(name, end='')
        print('跳舞----')
        time.sleep(0.5)
 #唱歌
def sing(num,name):  		#arg(,)元组参数
    for i in range(num):
        print(name, end='')
        print('唱歌----')
        time.sleep(0.3)
 if __name__ == '__main__':
    start_time= time.time()
    sing_process = multiprocessing.Process(target=sing, args=(10, '小明'))
    dance_process = multiprocessing.Process(target=dance, kwargs={'num': 5, 'name': '小花'})

    dance_process.start()
    sing_process.start()
    end_time = time.time()
    all_time = end_time-start_time
    print(f'时间:{all_time}')
(2)获取进程的编号
1.获取当前进程的编号      os.getpid()
2.获取当前父进程的编号()  os.getppid()  注意两个pp
# 跳舞
def dance(num, name):
    print('跳舞进程--pid:', os.getpid(),
          'n跳舞进程的父进程:', os.getppid())
    for i in range(num):
        print(name, end='')
        print('跳舞----')
        time.sleep(0.5)
# 跳舞
def dance(num, name):
    print('跳舞进程--pid:', os.getpid(),
          'n跳舞进程的父进程:', os.getppid())
    for i in range(num):
        print(name, end='')
        print('跳舞----')
        time.sleep(0.5)
if __name__ == '__main__':
	print('主进程的pid:', os.getpid())
    start_time= time.time()
    sing_process = multiprocessing.Process(target=sing, args=(10, '小明'))
    dance_process = multiprocessing.Process(target=dance, kwargs={'num': 5, 'name': '小花'})

    dance_process.start()
    sing_process.start()
    end_time = time.time()
    all_time = end_time-start_time
    print(f'时间:{all_time}')

———可查看到当前运行的进程编号,和父亲进程的编号————

多进程的编号注意点:
多进程的特点就是主进程——会等待所有的 子进程结束后才结束。
简单解释:打开QQ,找两个好友聊天,(两个好友的对话框就是两个子进程),并不是关闭QQ等待两个对话框关闭后QQ才关闭,
我们实际需求是关闭QQ程序,两个对话框会自动关闭。
——举个代码

def work():
    for i in range(10):
        print('----工作中---')
        time.sleep(0.2)

if __name__ =='__main__':
    #创建子进程:
    work_process = multiprocessing.Process(target=work)
    work_process.start()
    time.sleep(1)
    print('————主进程执行完成————')

——从图可知
主进程并不会结束后自动关闭 而是要等待 子进程结束后才关闭。

但是我们需求是:主程序关闭——子进程就关闭,
所以就有一个概念:守护主进程
他的作用就是为了实现主程序关闭 而关闭。

(3) 守护进程:
设置守护进程 子进程守护主进程,当主进程关闭 子进程将不再运行  
        进程名.daemon = True   
    主进程会默认等待子进程执行结束再结束进程  
如果是想让主进程结束子进程同样结束时 设置守护主进程就好 。


———需要注意的是:
进程名.daemon = True 代码要在子进程执行前。

Threading模块—— (1) threading——常用参数
参数说明
threading.active_count()现在运行的线程数量
threading.enumrate()显示现在运行的是哪个线程
threading.current_thread()正在运行的线程名
import threading

def main():
    print(threading.active_count()) 
    print(threading.enumerate())
    print(threading.current_thread())

if __name__ =='__main__':
    main()

threading.Tread(target=定义的线程函数名没有括号 只是为了方便索引,name =起的线程名字,args=传入线程名的参数) 和进程差不多。

线程名.start() 让线程的开始
线程名.join() 让线程的停止

值得注意的是:

(2)join()————子线程终止的使用。
''' 	多线程运行 并不是等待子线程运行完了以后  
才开始运行主线程,而是和子线程 ---同时运行--
但是有时为了子线程全部运行完了,才开始运行主线程后面的程序。
所以就需要 join()   
语法规则  ————线程名.join() '''

代码演示:

import threading
import time

def T1_job():
    print('T1 start')
    for i in range(10):
        time.sleep(0.1)
    print('T1--finish--')

def T2_job():
    print('T2 start')
    print('T2--finish--n')

def main():
    T1_thread = threading.Thread(target=T1_job, name='T1')
    T2_thread = threading.Thread(target=T2_job, name='T2')
    T1_thread.start()   
    T2_thread.start()
    # T1_thread.join()
    # T2_thread.join()
    print('all--done--')

if __name__ == '__main__':
    main()

结果显示————并没有等待子线程 T1 ,T2运行完才开始运行。而是同时进行的。

所以为了 所有的子线程运行完了
以后才开始运行主线程后面的 程序加上注释的 join()

结果显示————

(3)Lock()——子线程锁的运用。

——子线程和子线程之间运行的顺序是 无序的

import threading

def T1_job():
    global A,lock
    #lock.acquire()
    for i in range(10):
        A += 1
        print('T1-job', A)
    #lock.release()

def T2_job():
    global A,lock
    #lock.acquire()
    for i in range(10):
        A += 10
        print('T2-job', A)
    #lock.release()

if __name__ == '__main__':
    A = 0
    #lock = threading.Lock()
    T1_thread = threading.Thread(target=T1_job, name='T1')
    T2_thread = threading.Thread(target=T2_job, name='T2')
    T1_thread.start()
    T2_thread.start()
    T1_thread.join()
    T2_thread.join()

——定义两个线程 T1是每次加1,T2是每次加10

————可以看到运行的结果 :子进程之间并不是有序的运行。
没乱多运行七八次就可以 看到效果。

为了保证各个子线程运行中不被其他的子线程所打扰 就有一个lock
所以就调用treading中的Lock 锁住进程

lock = threading.Lock()
lock.acquire() 先得到
——代码块————
lock.release() 然后解锁**

取消上图的注释代码——可以看到 子线程之间是运行时互不打扰的。
_
_
_
_
_
_
——————如有错误不足之处指出 ,望各位及时指正————

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/286181.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号