9-3 線程,線程池,守護線程,鎖,協程

一 線程python

# 什麼是進程 :是計算機資源分配的最小單位
# 什麼是線程
# 線程和進程的關係 :
# 每個進程中都至少有一個線程
#開啓100個線程
 1 import os
 2 import time
 3 from threading import Thread
 4 n=100
 5 def func(i):
 6     global n
 7     time.sleep(1)
 8     n-=1
 9     print(os.getpid(),'thread%s'%i)
10 l=[]
11 for i in range(100):
12     t=Thread(target=func,args=(i,))
13     t.start()
14     l.append(t)
15 for i in l:
16     i.join()
17 print(n)


n的結果是0

總結:git

 #每一個進程裏至少有一個主線程負責執行代碼
# 在主線程中能夠再開啓一個新的線程
# 在同一個進程中就有兩個線程同時在工做了
# 線程纔是CPU調度的最小單位
# 多個線程之間的數據時共享的

二 守護線程
# 主線程結束了以後守護線程也同時結束
# 守護線程會等待主線程徹底結束以後才結束
from threading import Thread
import time
def foo():
    while True:
        print(123)
        time.sleep(1)
def bar():
    print(456)
    time.sleep(3)
    print('end456')
t1=Thread(target=foo)
t2=Thread(target=bar)
t1.daemon=True #foo是守護線程
t1.start()
t2.start()
print("main----") #主線程結束的地方

打印結果:
123
456
main----
123
123
end456

 三 鎖(Lock)github

1普通鎖 lock安全

# 當你的程序中出現了取值計算再賦值的操做 數據不安全 —— 加鎖
 1 from threading import Thread,Lock
 2 import time
 3 def work():
 4     global n
 5 
 6     lock.acquire()
 7     temp=n
 8     time.sleep(0.1)
 9     n=temp-1
10     lock.release()
11 if __name__ == '__main__':
12     lock = Lock()
13     n=100
14     l=[]
15     for i in range(10):
16         p=Thread(target=work)
17         l.append(p)
18         p.start()
19     for i in l:
20         i.join()
21     print(n)
22 
23 最後n的值爲90

2 遞歸鎖(Rlock)(不多用)app

1 from threading import RLock
2 
3 lock = RLock()
4 lock.acquire()
5 lock.acquire()
6 print(123)
7 lock.release()
8 print(456)
9 lock.release()

總結:dom

# 普通的鎖 在同一個線程中 只能acquire一次
# 因此當acquire兩次的時候就容易出現死鎖現象
# 出現了死鎖現象可使用遞歸鎖去解決問題
# 可是本質上死鎖的出現是由於邏輯的錯誤
# 所以咱們更應該把注意力集中在解決邏輯錯誤
# 而不要在出現錯誤的時候直接用遞歸鎖規避異步

遞歸鎖並無本質上解決死鎖的問題函數

 

四 線程池(ThreadPoolExecutor)ui

1url

 1 import time
 2 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
 3 def func(num):
 4     print(num)
 5     time.sleep(1)
 6     print(num)
 7 if __name__ == '__main__':
 8     t=ThreadPoolExecutor(20) #20個線程,每次處理20個
 9     for i in range(50):
10         t.submit(func,i) #異步提交命令
11     t.shutdown()#同join整個線程池
12     print('done')

2 回調函數(callback)

 1 # import time
 2 # import random
 3 # from concurrent.futures import ThreadPoolExecutor
 4 # from threading import current_thread
 5 # urls=[
 6 #         'https://www.baidu.com',
 7 #         'https://www.python.org',
 8 #         'https://www.openstack.org',
 9 #         'https://help.github.com/',
10 #         'http://www.sina.com.cn/'
11 #         'http://www.cnblogs.com/'
12 #         'http://www.sogou.com/'
13 #         'http://www.sohu.com/'
14 #     ]
15 #
16 # def analies(content):
17 #     print('分析網頁',current_thread())
18 #     print(content.result())
19 #
20 #
21 # def get_url(url):
22 #     print('爬取網頁',current_thread())
23 #     time.sleep(random.uniform(1,3))
24 #     # analies(url*10)
25 #     return url*10
26 #
27 # t = ThreadPoolExecutor(3)
28 # print('主線程',current_thread())
29 # for url in urls:
30 #     t.submit(get_url,url).add_done_callback(analies) #
#回調函數當執行了get_url以後,獲得了一個url*10 ,而後在當即執行analies函數,並傳給content參數

# concurrent.futures裏面的 callback是由子線程作的
 五協程(gevent)
須要手動安裝,第三方模塊
安裝 :pip3 install gevent
協程 把一個線程拆分紅幾個

# 協程 是程序級別調度
# 減輕了操做系統的負擔、加強了用戶對程序的可控性
 
特色是:只要遇到阻塞就會執行別的任務。例如:
from gevent import monkey;monkey.patch_all()
import gevent
import time
def eat(name):
    print('%s eat 1' %name)
    time.sleep(2)
    print('%s eat 2' %name)

def play(name):
    print('%s play 1' %name)
    time.sleep(1)
    print('%s play 2' %name)


g1=gevent.spawn(eat,'egon')
g2=gevent.spawn(play,'alex')
g1.join()
g2.join()
# gevent.joinall([g1,g2])#第二種寫法
print('')
執行結果是:

egon eat 1
alex play 1
alex play 2
egon eat 2



例2:利用協程批量訪問url
 1 from gevent import monkey;monkey.patch_all() #這個是必須加的不然gevent不識別time
 2 import gevent
 3 import requests
 4 import time
 5 
 6 def get_page(url):
 7     print('GET: %s' %url)
 8     response=requests.get(url)
 9     if response.status_code == 200:
10         print('%d bytes received from %s' %(len(response.text),url))
11 
12 
13 start_time=time.time()
14 gevent.joinall([
15     gevent.spawn(get_page,'https://www.python.org/'),
16     gevent.spawn(get_page,'https://www.yahoo.com/'),
17     gevent.spawn(get_page,'https://github.com/'),
18 ])
19 stop_time=time.time()
20 print('run time is %s' %(stop_time-start_time))
相關文章
相關標籤/搜索