线程、协成、IO模型
生活随笔
收集整理的這篇文章主要介紹了
线程、协成、IO模型
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1、線程就是CPU調(diào)度的最小單位。
2、 # 線程進(jìn)程之間的對(duì)比
# 線程不能獨(dú)立存在,必須在一個(gè)進(jìn)程里# 線程的開啟 關(guān)閉以及切換的開銷要遠(yuǎn)遠(yuǎn)小于進(jìn)程
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('主進(jìn)程')print(time.time() - start_time)
?
3、 # 同一個(gè)進(jìn)程之間的多個(gè)線程之間數(shù)據(jù)共享# 全局解釋器鎖GIL
# 使得一個(gè)進(jìn)程中的多個(gè)線程不能充分的利用多核
# 這個(gè)鎖能保證同一時(shí)刻只有一個(gè)線程運(yùn)行
4、 # 主線程如果結(jié)束了 那么整個(gè)進(jìn)程就結(jié)束
# 守護(hù)線程 會(huì)等待主線程結(jié)束之后才結(jié)束.
# 主進(jìn)程 等待 守護(hù)進(jìn)程 子進(jìn)程
# 守護(hù)進(jìn)程 只守護(hù)主進(jìn)程的代碼就可以了
# 守護(hù)線程不行 主線程如果結(jié)束了 那么整個(gè)進(jìn)程就結(jié)束 所有的線程就都結(jié)束 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
# 線程池對(duì)象.map(func,iterable)
# 線程池對(duì)象.submit 異步提交
# 線程池對(duì)象.shutdown ==>close+join
# 任務(wù)對(duì)象.result
# 任務(wù)對(duì)象.add_done_callback 回調(diào)函數(shù)都是在子線程執(zhí)行
# 進(jìn)程池
# concurrent.futures.ProcessPoolExecutor
# 任務(wù)對(duì)象.add_done_callback 回調(diào)函數(shù)都是在主進(jìn)程執(zhí)行
# 協(xié)程
# 在一個(gè)線程內(nèi)的多個(gè)任務(wù)之間能夠互相切換
# 這個(gè)切換不是操作系統(tǒng)級(jí)別的 都是用戶控制的
# 最簡(jiǎn)單的切換以及狀態(tài)的保留使用python原生的語法yield其實(shí)就可以實(shí)現(xiàn)
# 但是一般情況下我們都是用gevent來完成協(xié)程的工作
# 它能夠幫助我們規(guī)避IO操作
# 它內(nèi)部使用的協(xié)程機(jī)制是greenlet
# 協(xié)程比起線程的好處
# 充分的利用了一條線程來提高CPU的工作效率
# 不存在數(shù)據(jù)不安全的問題
# join() 在主線程中沒有其他阻塞事件的時(shí)候就是用join來保證協(xié)程任務(wù)都能順利的執(zhí)行完
# spawn() 發(fā)起一個(gè)協(xié)程任務(wù)
IO 模型
# IO多路復(fù)用 - 操作系統(tǒng)提供的
# 1.程序不能干預(yù)過程
# 2.操作系統(tǒng)之間的差異
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對(duì)象有數(shù)據(jù)可以被讀了
# 為什么返回三個(gè)列表? 讀事件的列表 寫事件的列表 條件的列表
# 為什么是列表? 有可能同時(shí)有多個(gè)被監(jiān)聽的對(duì)象發(fā)生讀時(shí)間
for obj in rl:
if obj is sk: # is的意思更精準(zhǔn),判斷的是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協(xié)議來說,如果對(duì)方關(guān)閉了連接
# 另一方有可能繼續(xù) 接收 空消息 或者 報(bào)錯(cuò)
# 背代碼
# 將具體的情況套到代碼中 將邏輯理順
# 理解之前IO多路復(fù)用的那張圖
# 什么叫IO多路復(fù)用
# io多路復(fù)用是操作系統(tǒng)提供的一種 監(jiān)聽 網(wǎng)絡(luò)IO操作的機(jī)制
# 監(jiān)聽三個(gè)列表
# 當(dāng)某一個(gè)列表有對(duì)應(yīng)的事件發(fā)生的時(shí)候
# 操作系統(tǒng)通知應(yīng)用程序
# 操作系統(tǒng)根據(jù)返回的內(nèi)容做具體的操作
# 對(duì)于只有一個(gè)對(duì)象需要監(jiān)聽的情況 IO多路復(fù)用并無法發(fā)揮作用
# 對(duì)于并發(fā)接收網(wǎng)絡(luò)請(qǐng)求的應(yīng)用場(chǎng)景 IO多路復(fù)用可以幫助你在節(jié)省CPU利用率和操作系統(tǒng)調(diào)用的基礎(chǔ)上完成并發(fā)需求
# IO多路復(fù)用
# select 是windows上的機(jī)制 輪詢的方式來監(jiān)聽每一個(gè)對(duì)象是否有對(duì)應(yīng)的事件發(fā)生的,數(shù)據(jù)越多延遲越大
# 能夠處理的對(duì)象數(shù)是有限的
# poll linux 和select的機(jī)制基本一致,對(duì)底層存儲(chǔ)被監(jiān)聽對(duì)象的數(shù)據(jù)結(jié)構(gòu)做了優(yōu)化
# 能夠處理的對(duì)象個(gè)數(shù)增加了
# epoll linux 采用了回調(diào)函數(shù)的方式來通知應(yīng)用被監(jiān)聽的對(duì)象有事件發(fā)生了
轉(zhuǎn)載于:https://www.cnblogs.com/zhaosijia/p/9391922.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的线程、协成、IO模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: django-celery使用
- 下一篇: REST、RESTful 与 RESTf