1. 程式人生 > >Python的Socket知識8:程序、資料共享、程序池

Python的Socket知識8:程序、資料共享、程序池

     程序(process)是cpu資源分配的最小單位,執行緒(thread)是cpu排程的最小單位。多執行緒和多程序的應用目的是為了提高併發。一個應用程式可以包含多個程序,而一個程序又可以包含多個執行緒。預設一個應用程式是單程序、單執行緒。

    主要講解建立程序的方法,以及實現共享的方式。

1、基本使用方法:

案例1:建立程序

from multiprocessing import Process
def foo(i):
print("hh",i)
if __name__ == '__main__':#在Windows下,此語句只能做測試用,不用在生產中用
   
li=[]
for i in range
(10):
p=Process(target=foo,args=(i,))
p.start()

執行結果:

640?wx_fmt=png

程序同樣有daemon和join方法,類似於執行緒

案例2:join() 也適用在程序中,逐個執行程序

    當一個執行緒操作需要等待另一個執行緒執行完畢之後才能繼續進行時,使用Join()方法。Join方法會等到使用該方法的執行緒結束後再執行下面的程式碼

from multiprocessing import Process
def foo(i):
print("hh",i)
if __name__ == '__main__':#在Windows下,此語句只能做測試用,不用在生產中用
   
li=[]
for i in range(10):
p=Process(target=foo,args=(i,))
p.start()
p.join(5)#逐個執行每個程序,執行完畢後,繼續往下執行
   
print('123')

執行結果:

640?wx_fmt=png

2、資料共享:

程序之間預設資料不共享,比如QQ和百度就不會共享資料,可以通過一些方法實現資料共享

案例3:不共享的案例

from multiprocessing import Process
import time
def foo(i,arg):
arg.append(i)
print("hh",i,arg)
if __name__ == '__main__'
:#在Windows下,此語句只能做測試用,不用在生產中用
   
li=[]
for i in range(10):
p=Process(target=foo,args=(i,li))
p.start()

執行結果:如果共享,則中括號中的資料i應該從0開始排列

640?wx_fmt=png

案例4,利用queues,實現程序的共享

from multiprocessing import Process
from multiprocessing import queues#特殊的功能,實現程序之間資料共享
import multiprocessing
def foo(i,arg):
arg.put(i)
print("hh",i,arg.qsize())
if __name__ == '__main__':#在Windows下,此語句只能做測試用,不用在生產中用
   
li=queues.Queue(20,ctx=multiprocessing)
for i in range(10):
p=Process(target=foo,args=(i,li))
p.start()

執行效果:

640?wx_fmt=png

案例5,利用array實現資料共享

from multiprocessing import Process, Array
def Foo(i,arg):
arg[i] = 100 + i
for item in arg:
print ('----->',item)
print('================')
if __name__ == '__main__':
li=Array('i',10)
for i in range(10):
p = Process(target=Foo, args=(i,li,))
p.start()

執行效果:

640?wx_fmt=png

案例6,利用manage實現資料共享

from multiprocessing import Process
from multiprocessing import Manager
def foo(i,arg):
arg[i] = i+100
   
print(arg.values())
if __name__ == '__main__':
obj=Manager()
li=obj.dict()
for i in range(10):
p = Process(target=foo,args=(i,li,))
p.start()
p.join()#控制子程序,或者用下面的time來控制主程序不終止
   # import time
   # time.sleep(0.1)

執行效果:

640?wx_fmt=png

3、程序鎖、條件、事件等,同線程鎖用法

案例7:程序鎖:同線程鎖的用法

from multiprocessing import Process,Array,RLock
import time
def foo(i,arg,lc):
lc.acquire()
arg[0]=arg[0]-1
   
time.sleep(1)
print("say hi",arg[0])
lc.release()
if __name__ == '__main__':
li=Array('i',1)
li[0]=10
   
lock=RLock()
for i in range(10):
p = Process(target=foo,args=(i,li,lock,))
p.start()

執行結果:

640?wx_fmt=png

4、程序池:

    程序池內部維護一個程序序列,當使用時,則去程序池中獲取一個程序,如果程序池序列中沒有可供使用的進程序,那麼程式就會等待,直到程序池中有可用程序為止

案例8:apply序列的方式執行

from multiprocessing import Pool
import time

def foo(arg):
time.sleep(1)
print("say hi",arg)

if __name__ == '__main__':
pool=Pool(5)
for i in range(10):
pool.apply(func=foo,args=(i,))#序列的方式執行
   
print("end")

執行結果:

640?wx_fmt=png

案例9:apply_async主程序執行完,不等子程序

from multiprocessing import Pool
import time

def foo(arg):
time.sleep(1)
print("say hi",arg)

if __name__ == '__main__':
pool=Pool(5)
for i in range(10):
# pool.apply(func=foo,args=(i,))#序列的方式執行
       
pool.apply_async(func=foo,args=(i,))#主程序執行完,不等子程序
   
print("end")

執行結果:end

案例10:teminate和close的終止方式

from multiprocessing import Pool
import time

def foo(arg):
time.sleep(1)
print("say hi",arg)

if __name__ == '__main__':
pool=Pool(5)
for i in range(10):
pool.apply_async(func=foo,args=(i,))#序列的方式執行
   
pool.close()#所有的任務全部執行完,程序繼續執行
   #pool.terminate()  #執行到此,立即終止
   
pool.join()

5、協程:

    協程是一種使用者態的輕量級執行緒,其實可以認為是比執行緒更小的執行單元。利用一個執行緒,分解一個執行緒成為多個"微執行緒"。

    協程存在的意義:執行緒切換從系統層面遠不止 儲存和恢復 CPU上下文這麼簡單。作業系統為了程式執行的高效性每個執行緒都有自己快取Cache等等資料,作業系統還會幫你做這些資料的恢復操作。所以執行緒的切換非常耗效能。但是協程的切換隻是單純的操作CPU的上下文,所以一秒鐘切換個上百萬次系統都抗的住。協程,則只使用一個執行緒,在一個執行緒中規定某個程式碼塊執行順序。

    協程的適用場景:當程式中存在大量不需要CPU的操作時(IO),適用於協程;

http://blog.csdn.net/qq910894904/article/details/41699541

案例11:協程gevent的應用

from gevent import monkey;monkey.patch_all()
import gevent
import requests
def f(url):
print('GEt:%s'%url)
resp=requests.get(url)
data=resp.text
print("%d bytes received from %s"%(len(data),url))
gevent.joinall([
gevent.spawn(f,'https://www.python.org'),
gevent.spawn(f,'https://www.baidu.com'),
gevent.spawn(f,'https://www.cnblogs.com/'),
])

執行結果:

640?wx_fmt=png

案例連結:https://pan.baidu.com/s/1snibPi1 密碼:jh96