這篇文章帶給大家的內容是關於PHP中的SAPI是什麼?如何實現? (圖文),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
Python是運行在解釋器中的語言,查找資料知道,python中有一個全域鎖定(GIL),在使用多進程(Thread)的情況下,不能發揮多核心的優勢。而使用多進程(Multiprocess),則可以發揮多核心的優勢真正提高效率。
如果多執行緒的進程是CPU密集型的,那多執行緒並不能有多少效率上的提升,相反還可能因為執行緒的頻繁切換,導致效率下降,推薦使用多進程;如果是IO密集型,多執行緒的進程可以利用IO阻塞等待時的空閒時間執行其他線程,提升效率。
1.Linux建立子程序的原理:
1). 父進程和子進程, 如果父進程結束, 子進程也隨之結束;
2). 先有父進程, 再有子進程, 透過fork函數實現;
2.fork函數的返回值:呼叫該方法一次, 返回兩次;
產生的子進程回傳一個0
#父進程回傳子程序的pid;
#3.Window也能使用fork函數麼?
Windows没有fork函数, Mac有fork函数(Unix -> Linux, Unix-> Mac), 封装了一个模块multiprocessing
4.常用方法:
import os import time print("当前进程(pid=%d)正在运行..." %(os.getpid())) print("当前进程的父进程(pid=%d)正在运行..." %(os.getppid())) print("正在创建子进程......") pid = os.fork() pid2 = os.fork() print("第1个:", pid) print("第2个: ", pid2) if pid == 0: print("这是创建的子进程, 子进程的id为%s, 父进程的id为%s" %(os.getpid(), os.getppid())) else: print("当前是父进程[%s]的返回值%s" %(os.getpid(), pid)) time.sleep(100)
RuntimeError:
An attempt has been made to start a new process before the current process has finished its bootstrapping phase. This probably means that you are not using fork to start your child processes and you have forgotten to use the proper idiom in the main module: if __name__ == '__main__': freeze_support() ... The "freeze_support()" line can be omitted if the program is not going to be frozen to produce an executable.
import multiprocessing def job(): print("当前子进程的名称为%s" %(multiprocessing.current_process())) if __name__=="__main__": #win操作系统需要加上,否则会出现异常报错RuntimeError # 创建一个进程对象(group=None, target=None, name=None, args=(), kwargs={}) p1 = multiprocessing.Process(target=job) p2 = multiprocessing.Process(target=job) # 运行多进程, 执行任务 p1.start() p2.start() # 等待所有的子进程执行结束, 再执行主进程的内容 p1.join() p2.join() print("任务执行结束.......")
#透過重寫multiprocessing.Process類別來建立多進程
from multiprocessing import Process import multiprocessing class JobProcess(Process): # 重写Process的构造方法, 获取新的属性 def __init__(self,queue): super(JobProcess, self).__init__() self.queue = queue # 重写run方法, 将执行的任务放在里面即可 def run(self): print("当前进程信息%s" %(multiprocessing.current_process())) if __name__=="__main__": processes = [] # 启动10个子进程, 来处理需要执行的任务; for i in range(10): #示例化类,创建进程 p = JobProcess(queue=3) processes.append(p) #启动多进程,执行任务 p.start() #等待所有的子进程结束,再执行主进程 [pro.join() for pro in processes] print("任务执行结束")
#守護程式
setDeamon: True: 主线程执行结束, 子线程不再继续执行; Flase:
#守護程式:
setDeamon: True: 主进程执行结束, 子进程不再继续执行; Flase:
import multiprocessing import time def deamon(): #守护进程:当主程序运行结束,子进程也结束 name = multiprocessing.current_process() print("%s开始执行" %(name)) time.sleep(3) print("执行结束") if __name__=="__main__": p1 = multiprocessing.Process(target=deamon,name='hello') p1.daemon = True p1.start() time.sleep(2) print("整个程序执行结束")
############ #####終止進程######有些進程或許再執行死循環任務,此時我們手動結束進程###terminate()###
import multiprocessing import time def job(): name = multiprocessing.current_process() print("%s进程开启" %(name)) time.sleep(3) print("进程结束") if __name__=="__main__": p = multiprocessing.Process(target=job) print("进程开启:",p.is_alive()) p.start() print("进程开启:",p.is_alive()) p.terminate() print("进程开启:",p.is_alive()) time.sleep(0.001) print("进程开启:",p.is_alive()) print("程序执行结束")############ ######計算密集型和I/O密集型######計算密集型任務的特點是要進行大量的運算, 消耗CPU資源, 例如計算圓周率、 對影片進行高畫質解碼等等,全靠CPU的運算能力。這種運算密集型任務雖然也可以用多任務完成, 但是任務越多, 花在任務切換的時間就越多, CPU執行任務的效率就越低, 所以, 要最高效地利用CPU, 計算密集型任務同時進行的數量應等於CPU的核心數。運算密集型任務由於主要消耗CPU資源, 因此, 程式碼運行效率至關重要。 Python這樣的腳本語言運作效率很低, 完全不適合計算密集型任務。對於計算密集型任務,最好用C語言編寫。 ######第二種任務的類型是IO密集型, 涉及到網路、 磁碟IO的任務都是IO密集型任務, 這類任務的特徵是CPU消耗很少, 任務的大部分時間都在等待IO操作完成(因為IO的速度遠低於CPU和記憶體的速度)。對於IO密集型任務, 任務越多, CPU效率越高, 但也有一個限度。常見的任務大多是IO密集型任務, 例如Web應用。 ######多進程和多執行緒對比######多進程模式最大的優點就是穩定性高, 因為一個子進程崩潰了, 不會影響主進程和其他子進程。 (當然主進程掛了所有進程就全掛了, 但是Master進程只負責分配任務, 掛掉的機率低)著名的Apache最早就是採用多進程模式。 ######多重處理模式的缺點是建立進程的代價大, 在Unix/Linux系統下, 用 fork 呼叫還行, 在Windows下建立進程開銷巨大。另外, 作業系統能同時運行的進程數也是有限的, 在記憶體和。 CPU的限制下, 如果有幾千個行程同時運行, 作業系統連調度都會成問題。 ###
多线程模式通常比多进程快一点, 但是也快不到哪去, 而且, 多线程模式致命的缺点就是任何一个线程挂掉都可能直接造成整个进程崩溃, 因为所有线程共享进程的内存。 在Windows上, 如果一个线程执行的代码出了问题, 你经常可以看到这样的提示:“该程序执行了非法操作, 即将关闭”, 其实往往是某个线程出了问题, 但是操作系统会强制结束整个进程。
这里通过一个计算密集型任务,来测试多进程和多线程的执行效率。
import multiprocessing import threading from mytimeit import timeit class JobProcess(multiprocessing.Process): def __init__(self,li): super(JobProcess, self).__init__() self.li = li def run(self): for i in self.li: sum(i) class JobThread(threading.Thread): def __init__(self,li): super(JobThread, self).__init__() self.li = li def run(self): for i in self.li: sum(i) @timeit def many_processs(): li = [[24892,23892348,239293,233],[2382394,49230,2321234],[48294,28420,29489]]*10 processes = [] for i in li : p = JobProcess(li) processes.append(p) p.start() [pro.join() for pro in processes] print("多进程执行任务结束,✌") @timeit def many_thread(): #创建进程和销毁进程是时间的,如果li长度不够,会造成多线程快过多进程 li = [[24892,23892348,239293,233],[2382394,49230,2321234],[48294,28420,29489]]*1000 threads = [] for i in li : t = JobThread(li) threads.append(t) t.start() [thread.join() for thread in threads] print("多线程执行任务结束,✌") if __name__ =="__main__": many_processs() many_thread()
演示了生产者和消费者的场景。生产者生产货物,然后把货物放到一个队列之类的数据结构中,生产货物所要花费的时间无法预先确定。消费者消耗生产者生产的货物的时间也是不确定的。
通过队列来实现进程间的通信
import multiprocessing import threading from multiprocessing import Queue class Producer(multiprocessing.Process): def __init__(self,queue): super(Producer, self).__init__() self.queue = queue def run(self): for i in range(13): #往队列添加内容 self.queue.put(i) print("生产者传递的消息为%s" %(i)) return self.queue class Consumer(multiprocessing.Process): def __init__(self,queue): super(Consumer, self).__init__() self.queue = queue def run(self): #获取队列内容 #get会自动判断队列是否为空,如果是空, 跳出循环, 不会再去从队列获取数据; while True: print("进程获取消息为:%s" %(self.queue.get())) if __name__=="__main__": queue = Queue(maxsize=100) p = Producer(queue) p.start() c = Consumer(queue) c.start() p.join() c.join(2) c.terminate() #终止进程 print("进程间通信结束,( •̀ ω •́ )y")
以上是python多進程的詳細介紹(附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!