網(wǎng)站開發(fā)和嵌入式開發(fā)哪個(gè)泉州網(wǎng)站seo外包公司
文章目錄
- 程序和進(jìn)程的概念 p173
- 函數(shù)式創(chuàng)建子進(jìn)程
- Process類常用的屬性和方法1 p175
- Process類中常用的屬性和方法2 p176
- 繼承式創(chuàng)建子進(jìn)程 p177
- 進(jìn)程池的使用 p178
- 并發(fā)和并行 p179
- 進(jìn)程之間數(shù)據(jù)是否共享 p180
- 隊(duì)列的基本使用 p180
- 使用隊(duì)列實(shí)現(xiàn)進(jìn)程之間的通信 p182
- 函數(shù)式創(chuàng)建線程 p183
- 繼承式創(chuàng)建線程 p184
- 線程之間數(shù)據(jù)共享 p185
程序和進(jìn)程的概念 p173
進(jìn)程是運(yùn)行態(tài)的程序
函數(shù)式創(chuàng)建子進(jìn)程
fork可以用于unix類的操作系統(tǒng):linux,macos
但是在windows系統(tǒng)中,只能使用Process,詳見(jiàn)下
第一種創(chuàng)建進(jìn)程的語(yǔ)法結(jié)構(gòu):
Process(group=None,target,name,args,kwargs)
參數(shù)說(shuō)明:
1、group:表示分組,實(shí)際上不使用,值默認(rèn)為None即可;可不寫
2、target:表示子進(jìn)程要執(zhí)行的任務(wù),支持函數(shù)名
3、name:表示子進(jìn)程的名稱;可不寫
4、args:表示調(diào)用函數(shù)的位置參數(shù),以元組的形式進(jìn)行傳遞;有就寫
5、kwargs:表示調(diào)用函數(shù)的關(guān)鍵字參數(shù),以字典的形式進(jìn)行傳遞;有就寫
代碼實(shí)例1:
import multiprocessing
import os
import timedef test():print(f'我是子進(jìn)程,我的PID是:{os.getpid()},我的父進(jìn)程是{os.getppid()}')time.sleep(1)if __name__=='__main__':print('主進(jìn)程開始執(zhí)行')lst=[]# 創(chuàng)建五個(gè)子進(jìn)程for i in range(5):# 創(chuàng)建單個(gè)子進(jìn)程p=multiprocessing.Process(target=test) # 返回值類型為:<class 'multiprocessing.context.Process'>print(type(p))# 啟動(dòng)子進(jìn)程p.start()# 啟動(dòng)中的進(jìn)程加到列表中lst.append(p)print('主進(jìn)程執(zhí)行結(jié)束')
上面的運(yùn)行結(jié)果是主進(jìn)程先結(jié)束,子進(jìn)程在逐個(gè)結(jié)束
若要求所有子進(jìn)程中的代碼執(zhí)行結(jié)束,主進(jìn)程在結(jié)束,可以使用join()方法,阻塞,見(jiàn)下面:
import multiprocessing
import os
import timedef test():print(f'我是子進(jìn)程,我的PID是:{os.getpid()},我的父進(jìn)程是{os.getppid()}')time.sleep(1)if __name__=='__main__':print('主進(jìn)程開始執(zhí)行')lst=[]# 創(chuàng)建五個(gè)子進(jìn)程for i in range(5):# 創(chuàng)建單個(gè)子進(jìn)程p=multiprocessing.Process(target=test) # 返回值類型為:<class 'multiprocessing.context.Process'># 啟動(dòng)子進(jìn)程p.start()# 啟動(dòng)中的進(jìn)程加到列表中lst.append(p)for item in lst:item.join() # 阻塞主進(jìn)程print('主進(jìn)程執(zhí)行結(jié)束')
Process類常用的屬性和方法1 p175
方法/屬性名稱 | 功能描述 |
---|---|
name | 當(dāng)前進(jìn)程實(shí)例別名,默認(rèn)為Process-N |
pid | 當(dāng)前進(jìn)程對(duì)象的PID值 |
is_alive() | 進(jìn)程是否執(zhí)行完,沒(méi)執(zhí)行完結(jié)果為True,否則為False |
join(timeout) | 等待結(jié)束或傳入了參數(shù)就是等待timeout秒 |
start() | 啟動(dòng)進(jìn)程 |
run() | 若沒(méi)有指定target參數(shù),則啟動(dòng)進(jìn)程后,會(huì)調(diào)用父類中的run方法 |
terminate() | 強(qiáng)制終止進(jìn)程 |
代碼實(shí)例:
import os,multiprocessing,timedef sub_process(name):print(f'子進(jìn)程pid:{os.getpid()},父進(jìn)程的pid:{os.getppid()},入?yún)ame={name}')time.sleep(1)def sub_process2(name):print(f'子進(jìn)程pid:{os.getpid()},父進(jìn)程的pid:{os.getppid()},入?yún)ame={name}')time.sleep(1)if __name__ == '__main__': # 直接寫main# 主進(jìn)程print('父進(jìn)程開始執(zhí)行')for i in range(5):# 創(chuàng)建第一個(gè)子進(jìn)程p1=multiprocessing.Process(target=sub_process,args=('ysj',))# 創(chuàng)建第二個(gè)子進(jìn)程p2=multiprocessing.Process(target=sub_process2,args=(18,))# 調(diào)用Process類的start方法啟動(dòng)子進(jìn)程p1.start()p2.start()# 調(diào)用進(jìn)程對(duì)象的類屬性print(p1.name,'是否執(zhí)行完畢:',not p1.is_alive())print(p2.name, '是否執(zhí)行完畢:', not p2.is_alive())p1.join() # 主程序阻塞等待p1結(jié)束p2.join() # 主程序阻塞等待p2結(jié)束print('父進(jìn)程執(zhí)行結(jié)束')
Process類中常用的屬性和方法2 p176
代碼實(shí)例1:
import os,multiprocessing,timeif __name__ == '__main__': # 直接寫main# 主進(jìn)程print('父進(jìn)程開始執(zhí)行')for i in range(5):# 創(chuàng)建第一個(gè)子進(jìn)程p1=multiprocessing.Process() # 沒(méi)有給定taget參數(shù),會(huì)調(diào)用執(zhí)行Process類中的run方法# 創(chuàng)建第二個(gè)子進(jìn)程p2=multiprocessing.Process()p1.start() # 調(diào)用Process類中的run方法去執(zhí)行p2.start()print('父進(jìn)程執(zhí)行結(jié)束')
代碼實(shí)例2:
import os,multiprocessing,timedef sub_process(name):print(f'子進(jìn)程pid:{os.getpid()},父進(jìn)程的pid:{os.getppid()},入?yún)ame={name}')time.sleep(1)def sub_process2(name):print(f'子進(jìn)程pid:{os.getpid()},父進(jìn)程的pid:{os.getppid()},入?yún)ame={name}')time.sleep(1)if __name__ == '__main__': # 直接寫main# 主進(jìn)程print('父進(jìn)程開始執(zhí)行')for i in range(5):# 創(chuàng)建第一個(gè)子進(jìn)程p1=multiprocessing.Process(target=sub_process,args=('ysj',)) # 沒(méi)有給定taget參數(shù),會(huì)調(diào)用執(zhí)行Process類中的run方法# 創(chuàng)建第二個(gè)子進(jìn)程p2=multiprocessing.Process(target=sub_process2,args=(18,))p1.start()p2.start()# 強(qiáng)制終止進(jìn)程p1.terminate()p2.terminate()print('父進(jìn)程執(zhí)行結(jié)束')
繼承式創(chuàng)建子進(jìn)程 p177
第二種創(chuàng)建進(jìn)程的語(yǔ)法結(jié)構(gòu):
class 子進(jìn)程(Process): # 繼承Process類,然后去重寫run方法pass
代碼實(shí)例:
import multiprocessing,time,os# 自定義一個(gè)類
class SubProcess(multiprocessing.Process): # 繼承Process類# 編寫一個(gè)初始化方法def __init__(self,name):# 調(diào)用父類的初始化方法super().__init__()self.name=name# 重寫父類的run方法def run(self):print(f'子進(jìn)程的名稱:{self.name},PID是:{os.getpid()},父進(jìn)程的PID是:{os.getppid()}')if __name__ == '__main__':print('父進(jìn)程開始執(zhí)行')lst=[]for i in range(1,6):p1=SubProcess(f'進(jìn)程:{i}')# 啟動(dòng)進(jìn)程p1.start() # 沒(méi)有參數(shù)會(huì)調(diào)用run方法lst.append(p1)# 阻塞主進(jìn)程,等待子進(jìn)程執(zhí)行完畢for item in lst:item.join()print('父進(jìn)程執(zhí)行結(jié)束')
進(jìn)程池的使用 p178
若要?jiǎng)?chuàng)建、管理的進(jìn)程有上百個(gè),創(chuàng)建、銷毀線程要消耗大量的時(shí)間。進(jìn)程池可以解決這個(gè)問(wèn)題
進(jìn)程池的原理:
創(chuàng)建一個(gè)進(jìn)程池,并設(shè)置進(jìn)程池中最大的進(jìn)程數(shù)量。假設(shè)進(jìn)程池中最大的進(jìn)程數(shù)為3,現(xiàn)在有10個(gè)任務(wù)需要執(zhí)行,name進(jìn)程池一次可以執(zhí)行3個(gè)任務(wù),4次即可完成全部任務(wù)的執(zhí)行。
創(chuàng)建進(jìn)程池的語(yǔ)法結(jié)構(gòu):
進(jìn)程池對(duì)象=Pool(N)
方法名 | 功能描述 |
---|---|
apply_async(func,args,kwargs) | 使用非阻塞方式調(diào)用函數(shù)func |
apply(func,args,kwargs) | 使用阻塞方式調(diào)用函數(shù)func |
close() | 關(guān)閉進(jìn)程池,不再接受新任務(wù) |
terminate() | 不管任務(wù)是否完成,立即終止 |
join() | 阻塞主進(jìn)程,必須在terminate()或close()之后使用 |
代碼實(shí)例:非阻塞運(yùn)行進(jìn)程池
import multiprocessing,os,time# 編寫任務(wù)
def task(name):print(f'子進(jìn)程的PID:{os.getpid()},父進(jìn)程的PID:{os.getppid()},執(zhí)行的任務(wù):{name}')time.sleep(1)if __name__ == '__main__':# 主進(jìn)程start=time.time() # 返回時(shí)間戳,單位是秒print(start,':父進(jìn)程開始執(zhí)行')# 創(chuàng)建進(jìn)程池p=multiprocessing.Pool(3)# 創(chuàng)建任務(wù)for i in range(10):# 以非阻塞方式p.apply_async(func=task,args=(i,))# 關(guān)閉進(jìn)程池不再接收新任務(wù)p.close()# 阻塞主進(jìn)程等待子進(jìn)程執(zhí)行完畢p.join()print(time.time()-start)print('父進(jìn)程執(zhí)行結(jié)束')
代碼實(shí)例:阻塞運(yùn)行進(jìn)程池
import multiprocessing,os,time# 編寫任務(wù)
def task(name):print(f'子進(jìn)程的PID:{os.getpid()},父進(jìn)程的PID:{os.getppid()},執(zhí)行的任務(wù):{name}')time.sleep(1)if __name__ == '__main__':# 主進(jìn)程start=time.time() # 返回時(shí)間戳,單位是秒print(start,':父進(jìn)程開始執(zhí)行')# 創(chuàng)建進(jìn)程池p=multiprocessing.Pool(3)# 創(chuàng)建任務(wù)for i in range(10):# 非阻塞方式p.apply(func=task,args=(i,))# 關(guān)閉進(jìn)程池不再接收新任務(wù)p.close()# 阻塞主進(jìn)程等待子進(jìn)程執(zhí)行完畢p.join()print(time.time()-start) # 非阻塞用了4秒多,阻塞方式用了10秒多print('父進(jìn)程執(zhí)行結(jié)束')
并發(fā)和并行 p179
并發(fā):
是指兩個(gè)或多個(gè)事件在 同一時(shí)間間隔 發(fā)生,多個(gè)任務(wù)被交替輪換著執(zhí)行,比如A事件在吃蘋果,在吃蘋果的過(guò)程中有快遞員敲門讓你收下快遞,收快遞就是B事件,name收完快遞繼續(xù)吃沒(méi)吃完的蘋果。就是并發(fā)。
并行:
指兩個(gè)或多個(gè)事件在同一時(shí)刻發(fā)生,多個(gè)任務(wù)在同一時(shí)刻在多個(gè)處理器上同時(shí)執(zhí)行。比如A事件是泡腳,B事件是打電話,C事件是記錄電話內(nèi)容,這三件事則可以在同一時(shí)刻發(fā)生,這就是并行。
進(jìn)程之間數(shù)據(jù)是否共享 p180
Python當(dāng)中的并行對(duì)應(yīng)多進(jìn)程
代碼實(shí)例:
import multiprocessing,osa=100def add():print('子進(jìn)程1開始執(zhí)行')global aa+=30print('a=',a)print('子進(jìn)程1執(zhí)行完畢')def sub():print('子進(jìn)程2開始執(zhí)行')global aa-=50print('a=',a)print('子進(jìn)程2執(zhí)行完畢')if __name__ == '__main__':# 父進(jìn)程print('父進(jìn)程開始執(zhí)行')# 創(chuàng)建加的子進(jìn)程p1=multiprocessing.Process(target=add)# 創(chuàng)建減的子進(jìn)程p2=multiprocessing.Process(target=sub())# 啟動(dòng)子進(jìn)程p1.start()p2.start()# 主進(jìn)程阻塞,等待子進(jìn)程執(zhí)行完成p1.join()p2.join()print('父進(jìn)程結(jié)束執(zhí)行')
發(fā)現(xiàn)結(jié)果分別為 130和50,由此發(fā)現(xiàn)多進(jìn)程之間的數(shù)據(jù)不是共享的,子進(jìn)程1中有一份a,子進(jìn)程2中還有另一份a
如何解決進(jìn)程之間的數(shù)據(jù)共享,見(jiàn)下一節(jié)
隊(duì)列的基本使用 p180
進(jìn)程之間可以通過(guò)隊(duì)列(queue)
進(jìn)行通信
隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)
創(chuàng)建隊(duì)列的語(yǔ)法結(jié)構(gòu):
隊(duì)列對(duì)象=Queue(N)
方法名稱 | 功能描述 |
---|---|
qsize() | 獲取當(dāng)前隊(duì)列包含的消息數(shù)量 |
empty() | 判斷隊(duì)列是否有空,為空結(jié)果為True,否則為False |
full() | 判斷隊(duì)列是否滿了,滿結(jié)果為True,否則為False |
get(block=True) | 獲取隊(duì)列中的一條消息,然后從隊(duì)列中移除,block默認(rèn)值為True(隊(duì)列為空時(shí)會(huì)阻塞等待消息) |
get_nowait() | 相當(dāng)于 get(block=False) ,消息隊(duì)列為空時(shí),拋出異常 |
put(item,block=True) | 將item消息放入隊(duì)列,block默認(rèn)為True(隊(duì)列滿時(shí)會(huì)阻塞等待隊(duì)列有空間) |
put_nowait(item) | 相當(dāng)于 put(item,block=False) |
代碼實(shí)例:
import multiprocessingif __name__ == '__main__':# 創(chuàng)建一個(gè)隊(duì)列q=multiprocessing.Queue(3) # 這個(gè)隊(duì)列最多可以接收3條信息print('隊(duì)列是否有空?',q.empty())print('隊(duì)列是否為滿?',q.full())print('隊(duì)列中的消息數(shù)?',q.qsize())print('-'*88)# 向隊(duì)列中添加信息q.put('hello')q.put('world')print('隊(duì)列是否有空?', q.empty())print('隊(duì)列是否為滿?', q.full())print('隊(duì)列中的消息數(shù)?', q.qsize())print('-'*88)q.put('11111111')print('隊(duì)列是否有空?', q.empty())print('隊(duì)列是否為滿?', q.full())print('隊(duì)列中的消息數(shù)?', q.qsize())print('-' * 88)print(q.get())print('隊(duì)列中的消息數(shù)?', q.qsize())print(q.get())print(q.get())print('隊(duì)列中的消息數(shù)?', q.qsize())'''
隊(duì)列的遍歷:
for i in range(q.qsize()):q.get_nowait()
'''
使用隊(duì)列實(shí)現(xiàn)進(jìn)程之間的通信 p182
代碼實(shí)例1:
import multiprocessingif __name__ == '__main__':q=multiprocessing.Queue(3)# 向隊(duì)列中添加元素q.put('hello')q.put('world')q.put('python')q.put('html',block=True,timeout=2) # 阻塞等待,最多兩秒,若到了兩秒會(huì)報(bào)錯(cuò)返回
代碼實(shí)例2:
import multiprocessing,timea=100# 入隊(duì)
def write_msg(q):global a # 要在函數(shù)內(nèi)使用全局變量,一定要先用此方法聲明if not q.full():for i in range(6):a-=10q.put(a)print(f'a入隊(duì)時(shí)的值:{a}')# 出隊(duì)
def read_msg(q):time.sleep(1)while q.qsize()>0:print(f'出隊(duì)時(shí)a的值:{q.get()}')if __name__ == '__main__':print('父進(jìn)程開始執(zhí)行')q=multiprocessing.Queue() # 不寫參數(shù)表示隊(duì)列接收的消息個(gè)數(shù)是沒(méi)有上限的# 創(chuàng)建兩個(gè)子進(jìn)程p1=multiprocessing.Process(target=write_msg,args=(q,))p2=multiprocessing.Process(target=read_msg, args=(q,))# 啟動(dòng)兩個(gè)子進(jìn)程p1.start()p2.start()# 等待寫的進(jìn)程結(jié)束,再去執(zhí)行主進(jìn)程p1.join()p2.join()print('父進(jìn)程執(zhí)行完畢')
函數(shù)式創(chuàng)建線程 p183
線程是cpu可調(diào)度的最小單位,被包含在進(jìn)程中,是進(jìn)程中實(shí)際的運(yùn)作單位。
一個(gè)進(jìn)程可以擁有N多個(gè)線程并發(fā)執(zhí)行,而每個(gè)線程并行執(zhí)行不同的任務(wù)。
創(chuàng)建線程的方法有兩種:函數(shù)式創(chuàng)建線程和繼承式創(chuàng)建線程
函數(shù)式創(chuàng)建線程的語(yǔ)法結(jié)構(gòu):
t=Thread(group,target,name,args,kwargs)
參數(shù)說(shuō)明:
1、group:創(chuàng)建線程對(duì)象的進(jìn)程組
2、target:創(chuàng)建線程對(duì)象所要執(zhí)行的目標(biāo)函數(shù)
3、name:創(chuàng)建線程對(duì)象的名稱,默認(rèn)為 Thread-n
4、args:用元組以位置參數(shù)的形式傳入target對(duì)應(yīng)函數(shù)的參數(shù)
5、kwargs:用字典以關(guān)鍵字參數(shù)的形式傳入target對(duì)應(yīng)函數(shù)的參數(shù)
代碼實(shí)例:
import threading,time# 編寫線程執(zhí)行函數(shù)
def test():for i in range(3):time.sleep(1)print(f'線程名:{threading.current_thread().name},正在執(zhí)行{i}') # 獲取當(dāng)前的線程對(duì)象threading.current_thread()if __name__ == '__main__':start=time.time()print('主線程開始執(zhí)行')# 線程lst=[threading.Thread(target=test) for i in range(2)]for item in lst: # item的數(shù)據(jù)類型就是Thread類型# 啟動(dòng)線程item.start()for item in lst:item.join()print('主線程執(zhí)行完畢')print(f'一共耗時(shí){time.time()-start}秒')# 一共有一個(gè)進(jìn)程,三個(gè)線程(一個(gè)主線程,兩個(gè)子線程)
繼承式創(chuàng)建線程 p184
使用Thread子類創(chuàng)建線程的操作步驟:
1、自定義類繼承threading模塊下的Thread類
2、實(shí)現(xiàn)run方法
代碼實(shí)例:
import threading,timeclass SubThread(threading.Thread):def run(self):for i in range(3):time.sleep(1)print(f'線程:{threading.current_thread().name}正在執(zhí)行{i}')if __name__ == '__main__':print('主線程開始執(zhí)行')# 使用列表生成式去創(chuàng)建線程對(duì)象lst=[SubThread() for i in range(2)]for item in lst:item.start()for item in lst:item.join()print('主線程執(zhí)行完畢')
線程之間數(shù)據(jù)共享 p185
線程之間的數(shù)據(jù)可以共享嗎?
import threadinga=100def add():print('加線程開始執(zhí)行')global aa+=30print(f'a的值為{a}')print('加線程執(zhí)行完成')def sub():print('減線程開始執(zhí)行')global aa-=50print(f'a的值為{a}')print('減線程執(zhí)行完成')if __name__ == '__main__':print('主線程開始執(zhí)行')print(f'全局變量a的值為{a}')add=threading.Thread(target=add)sub=threading.Thread(target=sub)add.start() # a=130sub.start() # a=80add.join()sub.join()print('主線程執(zhí)行完成')
由此可以得到結(jié)論:線程之間是可以共享數(shù)據(jù)的,進(jìn)程之間不可以共享數(shù)據(jù)