线程、协成、IO模型
生活随笔
收集整理的這篇文章主要介紹了
线程、协成、IO模型
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、線程就是CPU調度的最小單位。
2、 # 線程進程之間的對比
# 線程不能獨立存在,必須在一個進程里# 線程的開啟 關閉以及切換的開銷要遠遠小于進程
import time from threading import Thread from multiprocessing import Process def func(i):i += 1 if __name__ == '__main__':start_time = time.time()t_l = []for i in range(50):t = Thread(target=func, args=(i,))t.start()t_l.append(t)for t in t_l:t.join()print('主線程')print(time.time() - start_time) if __name__ == '__main__':start_time = time.time()p_l = []for i in range(50):p = Process(target=func, args=(i,))p.start()p_l.append(t)for p in t_l:p.join()print('主進程')print(time.time() - start_time)
?
3、 # 同一個進程之間的多個線程之間數據共享# 全局解釋器鎖GIL
# 使得一個進程中的多個線程不能充分的利用多核
# 這個鎖能保證同一時刻只有一個線程運行
4、 # 主線程如果結束了 那么整個進程就結束
# 守護線程 會等待主線程結束之后才結束.
# 主進程 等待 守護進程 子進程
# 守護進程 只守護主進程的代碼就可以了
# 守護線程不行 主線程如果結束了 那么整個進程就結束 所有的線程就都結束 import time from threading import Thread def thread1():while True:print(True)time.sleep(0.5)def thread2():print('in t2 start')time.sleep(3)print('in t2 end')if __name__ == '__main__':t1 = Thread(target=thread1)t1.setDaemon(True)t1.start()t2 = Thread(target=thread2)t2.start()time.sleep(1)print('主線程')
?
# 線程池# concurrent.futures.ThreadPoolExecutor
# 線程池對象.map(func,iterable)
# 線程池對象.submit 異步提交
# 線程池對象.shutdown ==>close+join
# 任務對象.result
# 任務對象.add_done_callback 回調函數都是在子線程執行
# 進程池
# concurrent.futures.ProcessPoolExecutor
# 任務對象.add_done_callback 回調函數都是在主進程執行
# 協程
# 在一個線程內的多個任務之間能夠互相切換
# 這個切換不是操作系統級別的 都是用戶控制的
# 最簡單的切換以及狀態的保留使用python原生的語法yield其實就可以實現
# 但是一般情況下我們都是用gevent來完成協程的工作
# 它能夠幫助我們規避IO操作
# 它內部使用的協程機制是greenlet
# 協程比起線程的好處
# 充分的利用了一條線程來提高CPU的工作效率
# 不存在數據不安全的問題
# join() 在主線程中沒有其他阻塞事件的時候就是用join來保證協程任務都能順利的執行完
# spawn() 發起一個協程任務
IO 模型
# IO多路復用 - 操作系統提供的
# 1.程序不能干預過程
# 2.操作系統之間的差異
import select
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9090))
sk.listen()
sk.setblocking(False)
rlst = [sk]
while True:
rl,wl,xl = select.select(rlst,[],[]) #[sk,conn1,conn2]
# 為什么突然把sk返回回來了? sk對象有數據可以被讀了
# 為什么返回三個列表? 讀事件的列表 寫事件的列表 條件的列表
# 為什么是列表? 有可能同時有多個被監聽的對象發生讀時間
for obj in rl:
if obj is sk: # is的意思更精準,判斷的是obj就是sk
conn,addr = obj.accept()
rlst.append(conn)
else:
try:
ret = obj.recv(1024)
print(ret)
obj.send(b'hello')
except ConnectionResetError:
obj.close()
rlst.remove(obj)
# TCP協議來說,如果對方關閉了連接
# 另一方有可能繼續 接收 空消息 或者 報錯
# 背代碼
# 將具體的情況套到代碼中 將邏輯理順
# 理解之前IO多路復用的那張圖
# 什么叫IO多路復用
# io多路復用是操作系統提供的一種 監聽 網絡IO操作的機制
# 監聽三個列表
# 當某一個列表有對應的事件發生的時候
# 操作系統通知應用程序
# 操作系統根據返回的內容做具體的操作
# 對于只有一個對象需要監聽的情況 IO多路復用并無法發揮作用
# 對于并發接收網絡請求的應用場景 IO多路復用可以幫助你在節省CPU利用率和操作系統調用的基礎上完成并發需求
# IO多路復用
# select 是windows上的機制 輪詢的方式來監聽每一個對象是否有對應的事件發生的,數據越多延遲越大
# 能夠處理的對象數是有限的
# poll linux 和select的機制基本一致,對底層存儲被監聽對象的數據結構做了優化
# 能夠處理的對象個數增加了
# epoll linux 采用了回調函數的方式來通知應用被監聽的對象有事件發生了
轉載于:https://www.cnblogs.com/zhaosijia/p/9391922.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的线程、协成、IO模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: django-celery使用
- 下一篇: REST、RESTful 与 RESTf