Threading用於提供線程相關的操做,線程是應用程序中工做的最小單元。
python
1 #!/usr/bin/env python 2 #_*_ coding:utf-8 _*_ 3 import threading 4 import time 5 6 def show(arg): 7 time.sleep(1) 8 print('threading' + str(arg)) 9 10 for i in range(10): 11 t = threading.Thread(target=show, args=(i,)) 12 t.start() 13 14 print ('main thread stop!')
上述代碼建立了10個「前臺」線程,而後控制器就交給了CPU,CPU根據指定算法進行調度,分片執行指令。git
更多方法:程序員
若是是後臺線程,主線程執行過程當中,後臺線程也在進行,主線程執行完畢後,後臺線程不論成功與否,均中止。github
若是是前臺線程,主線程執行過程當中,前臺線程也在進行,主線程執行完畢後等待前臺線程也執行完成後,程序中止。算法
因爲線程之間是進行隨機調度,而且每一個線程可能只執行n條以後,CPU接着執行其它線程,因此,可能出現以下問題:多線程
#!/usr/bin/env python #_*_coding:utf-8_*_ import threading import time gl_num = 0 def show(arg): global gl_num time.sleep(1) gl_num += 1 print gl_num for i in range(10): t = threading.Thread(target=show, args=(i,)) t.start() print 'main thread stop!'
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 import threading 5 import time 6 7 gl_num = 0 8 9 lock = threading.Rlock() 10 11 def Func(): 12 lock.acquire() 13 global gl_num 14 gl_num += 1 15 time.sleep(1) 16 print gl_num 17 lock.release() 18 19 for i in range(10): 20 t = threading.Thread(target=Func) 21 t.start()
python線程的事件用於主線程控制其它線程的執行,事件主要提供了三個方法set,wait,clear.app
事件處理的機制:全局定義了一個「Flag」,若是「Falg」值爲False,那麼當程序執行event.wait方法時就會阻塞,若是「Falg」值爲True,那麼執行event.wait方法時便再也不阻塞。async
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 import threading 5 6 def do(event): 7 print('start') 8 event.wait() 9 print('execute') 10 11 event_obj = threading.Event() 12 for i in range(10): 13 t = threading.Thread(target=do, args=(event_obj,)) 14 t.start() 15 16 event_obj.clear() 17 inp = raw_input('input:') 18 if inp == 'true': 19 event_obj.set()
1 from multiprocessing import Process 2 import threading 3 import time 4 5 def foo(i): 6 print ('Hello victor!', i) 7 8 for i in range(10): 9 p = Process(target=foo, args=(i,)) 10 p.start()
注意:因爲進程之間的數據須要各自持有一份,因此建立進程須要很是大的開銷。ide
進程各自持有一份數據,默認沒法共享數據。ui
#!/usr/bin/env python # _*_coding:utf-8_*_ from multiprocessing import Process from multiprocessing import Manager import time li = [] def foo(i): li.append(i) print('Hello victor!', li) for i in range(10): p = Process(target=foo, args=(i,)) p.start() print ('hehe', li)
1 # 方法一,Array 2 from multiprocessing import Process, Array 3 temp = Array('i', [1,2,3,4]) 4 5 def Foo(i): 6 temp[i] = 10 + i 7 for i in temp: 8 print i, '------' ,item 9 10 for i in range(2): 11 p = Process(target=Foo, args=(i,)) 12 p.start() 13 14 15 # 方法二: manage.dict()共享數據 16 from multiprocessing import Process, Manager 17 18 manage = Manage() 19 dic = manage.dict() 20 21 def Foo(i): 22 dic[i] = 10 + i 23 print dic.values() 24 25 for i in range(2): 26 p = Process(target=Foo, args=(i,)) 27 p.start() 28 p.join()
'c': ctypes.c_char, 'u': ctypes.c_wchar, 'b': ctypes.c_byte, 'B': ctypes.c_ubyte, 'h': ctypes.c_short, 'H': ctypes.c_ushort, 'i': ctypes.c_int, 'I': ctypes.c_uint, 'l': ctypes.c_long, 'L': ctypes.c_ulong, 'f': ctypes.c_float, 'd': ctypes.c_double
當建立進程時(非使用時),共享數據會被拿到子進程中,當進程中執行完畢後,再賦值給原值。
#!/usr/bin/env python # _*_coding:utf-8_*_ from multiprocessing import Process, Array, RLock def Foo(lock, temp, i): ''' 將第0個數加100 ''' lock.acquire() temp[0] = 100 + i for item in temp: print (i, '-----', item) lock.release() lock = RLock() temp = Array('i', [11,22,33,44]) for i in range(20): p = Process(target=Foo,args=(lock, temp, i, )) p.start()
進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,若是進程池序列中沒有可供使用的進程,那麼程序就會等待,直到進程池中有可用進程爲止。
進程池中有兩個方法:
1 #!/usr/bin/env python 2 # _*_coding:utf-8_*_ 3 from multiprocessing import Process, Pool 4 import time 5 6 def Foo(i): 7 time.sleep(2) 8 return i + 100 9 10 def Bar(arg): 11 print (arg) 12 13 pool = Pool(5) 14 #print pool.apply(Foo,(1,)) 15 #print pool.apply.async(func = Foo, args=(1,)).get() 16 17 for i in range(10): 18 pool.apply_async(func=Foo, args=(i,), callback=Bar) 19 20 print ('end') 21 pool.close() 22 pool.join() # 進程池中進程執行完畢後再關閉,若是註釋,那麼程序直接關閉。
線程和進程的操做是由程序觸發系統接口,最後的執行者是系統,協程的操做則是程序員。
協程存在的意義:對於多線程應用,CPU經過切片的方式來切換線程間的執行,線程切換時須要耗時(保存狀態,下次繼續)。協程,則只使用一個線程,在一個線程中規定某個代碼塊執行順序。
協程的使用場景:當程序中存在大量不須要CPU的操做時(IO操做),適合協程。
1 #!/usr/bin/env python 2 # _*_coding:utf-8_*_ 3 4 from greenlet import greenlet 5 6 def test1(): 7 print 1 8 gr2.switch() 9 print 2 10 gr2.switch() 11 12 def test2(): 13 print 3 14 gr1.switch() 15 print 4 16 17 gr1 = greenlet(test1) 18 gr2 = greenlet(test2) 19 gr1.switch()
1 import gevent 2 3 def foo(): 4 print ('Running in foo...') 5 gevent.sleep(0) 6 print ('Explicit context switch to foo again...') 7 8 def bar(): 9 print ('Explicit context to bar...') 10 gevent.sleep(0) 11 print ('Implicit context switch back to bar...') 12 13 gevent,joinall([ 14 gevent.spawn(foo), 15 gevent.spawn(bar), 16 ])
遇到IO自動切換:
from gevent import monkey from gevent import monkey.patch_all() import gevent import urllib2 def f(url): print ('GET: %s ' % url) resp = urllib2.urlopen(url) data = resp.read() print ('%d bytes received from %s.' % (len(data), url)) gevent.join([ gevent.spawn(f, 'https://www.python.org/'), gevent.spawn(f, 'https://www.yahoo.com/'), gevent.spawn(f, 'https://github.com/'), ])