" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python全棧之線程詳解

 更新時(shí)間:2021年12月24日 17:14:53   作者:熬夜泡枸杞  
這篇文章主要為大家介紹了Python全棧之線程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

1. 線程的概念

1.1 Manager_進(jìn)程通信

# ### Manager ( list 列表  ,  dict 字典 ) 進(jìn)程之間共享數(shù)據(jù)
from multiprocessing import Process , Manager ,Lock
def mywork(data,lock):
	# 共享字典
	"""
	lock.acquire()
	data["count"] -= 10
	lock.release()
	"""
	# 共享列表
	data[0] += 1
if __name__ == "__main__":
	lst = []
	m = Manager()
	lock = Lock()
	# 多進(jìn)程中的共享字典
	# data = m.dict(  {"count":5000}  )
	# print(data , type(data) )
	# 多進(jìn)程中的共享列表
	data =  m.list( [100,200,300] )
	# print(data , type(data) )
	""""""
	# 進(jìn)程數(shù)超過(guò)1000,處理該數(shù)據(jù),死機(jī)(謹(jǐn)慎操作)
	for i in range(10):
		p = Process(target=mywork,args=(data,lock))
		p.start()
		lst.append(p)
	# 必須等待子進(jìn)程所有計(jì)算完畢之后,再去打印該字典,否則報(bào)錯(cuò);
	for i in lst:
		i.join()
	print(data)

1.2 線程的概念

線程概念:

#進(jìn)程是資源分配的最小單位
#線程是計(jì)算機(jī)中調(diào)度的最小單位
#線程的緣起
資源分配需要分配內(nèi)存空間,分配cpu:
分配的內(nèi)存空間存放著臨時(shí)要處理的數(shù)據(jù)等,比如要執(zhí)行的代碼,數(shù)據(jù)
而這些內(nèi)存空間是有限的,不能無(wú)限分配
目前配置高的主機(jī),5萬(wàn)個(gè)并發(fā)已是上限.線程概念應(yīng)用而生.
#線程的特點(diǎn)
線程是比較輕量級(jí),能干更多的活,一個(gè)進(jìn)程中的所有線程資源是共享的.
一個(gè)進(jìn)程至少有一個(gè)線程在工作

線程的缺陷:

#python中的線程可以并發(fā),但是不能并行(同一個(gè)進(jìn)程下的多個(gè)線程不能分開(kāi)被多個(gè)cpu同時(shí)執(zhí)行)
#原因:
   全局解釋器鎖(Cpython解釋器特有) GIL鎖:
   同一時(shí)間,一個(gè)進(jìn)程下的多個(gè)線程只能被一個(gè)cpu執(zhí)行,不能實(shí)現(xiàn)線程的并行操作   
   python是解釋型語(yǔ)言,執(zhí)行一句編譯一句,而不是一次性全部編譯成功,不能提前規(guī)劃,都是臨時(shí)調(diào)度
   容易造成cpu執(zhí)行調(diào)度異常.所以加了一把鎖叫GIL   	
#想要并行的解決辦法:
    (1)用多進(jìn)程間接實(shí)現(xiàn)線程的并行
    (2)換一個(gè)Pypy,Jpython解釋器
#程序分為計(jì)算密集型和io密集型
	對(duì)于計(jì)算密集型程序會(huì)過(guò)度依賴cpu,但網(wǎng)頁(yè),爬蟲(chóng),OA辦公,這種io密集型的程序里,python綽綽有余

小結(jié):

進(jìn)程中的線程,同一時(shí)間只能有一個(gè)cup(單核來(lái)回切換進(jìn)行處理線程)來(lái)執(zhí)行,單核之間可以進(jìn)程切換
工作,以避免一個(gè)單核持續(xù)工作,過(guò)熱導(dǎo)致頻率降低。(java可以在同一時(shí)間進(jìn)行多核操作,也就是同步操作)
線程是執(zhí)行調(diào)度的最小單位
一個(gè)進(jìn)程包含多個(gè)線程,一個(gè)進(jìn)程至少一個(gè)線程
線程在一個(gè)進(jìn)程當(dāng)中可以共享一份資源
線程的缺陷:不能并行(java可以)
一個(gè)程序,至少一個(gè)主進(jìn)程和一個(gè)主線程

在這里插入圖片描述

2. 線程的基本使用

# ### 線程 
"""
進(jìn)程是資源分配的最小單元
線程是cpu執(zhí)行調(diào)度的最小單元
"""
# (1) 一個(gè)進(jìn)程里包含了多個(gè)線程,線程之間是異步并發(fā)
from threading import Thread
from multiprocessing import Process
import os , time , random
"""
def func(i):
	time.sleep(random.uniform(0.1,0.9))
	print("當(dāng)前進(jìn)程號(hào):{}".format(os.getpid()) , i)
if __name__ == "__main__":
	for i in range(10):
		t = Thread(target=func,args=(i,))
		t.start()
print(os.getpid())
"""
# (2) 并發(fā)的多進(jìn)程和多線程之間,多線程的速度更快
# 多線程速度
def func(i):
	print( "當(dāng)前進(jìn)程號(hào):{} , 參數(shù)是{} ".format(os.getpid() , i)  )
"""
if __name__ == "__main__":
	lst = []
	startime = time.time()
	for i in range(10000):
		t = Thread(target=func,args=(i,))
		t.start()
		lst.append(t)
	# print(lst)
	for i in lst:
		i.join()
	endtime = time.time()
	print("運(yùn)行的時(shí)間是{}".format(endtime - startime) ) # 運(yùn)行的時(shí)間是1.8805944919586182
"""
# 多進(jìn)程速度
"""
if __name__ == "__main__":
	lst = []
	startime = time.time()
	for i in range(10000):
		p = Process(target=func,args=(i,))
		p.start()
		lst.append(p)
	# print(lst)
	for i in lst:
		i.join()
	endtime = time.time()
	print("運(yùn)行的時(shí)間是{}".format(endtime - startime) ) # 運(yùn)行的時(shí)間是101.68004035949707
"""
# (3) 多線程之間,數(shù)據(jù)共享
num = 100
lst = []
def func():
	global num
	num -= 1
for i in range(100):
	t = Thread(target=func)
	t.start()
	lst.append(t)
for i in lst:
	i.join()
print(num)

在這里插入圖片描述

小提示: 一個(gè)線程對(duì)變量進(jìn)行操作的時(shí)候,其他的線程就不能在對(duì)這個(gè)變量進(jìn)行操作。這個(gè)時(shí)候用鎖把線程鎖住。

3. 自定義線程_守護(hù)線程

3.1 自定義線程

# ### 用類定義線程
from threading import Thread
import os,time
# (1)必須繼承父類Thread,來(lái)自定義線程類
"""
class MyThread(Thread):
	def __init__(self,name):
		# 手動(dòng)調(diào)用父類的構(gòu)造方法
		super().__init__()
		# 自定義當(dāng)前類需要傳遞的參數(shù)
		self.name = name
	def run(self):
		print(  "當(dāng)前進(jìn)程號(hào){},name={}".format(os.getpid() , self.name)  )
if __name__ == "__main__":
	t = MyThread("我是線程")
	t.start()
	print( "當(dāng)前進(jìn)程號(hào){}".format(os.getpid()) )
"""
# ### 線程中的相關(guān)屬性
"""
# 線程.is_alive()    檢測(cè)線程是否仍然存在
# 線程.setName()     設(shè)置線程名字
# 線程.getName()     獲取線程名字
# 1.currentThread().ident 查看線程id號(hào) 
# 2.enumerate()        返回目前正在運(yùn)行的線程列表
# 3.activeCount()      返回目前正在運(yùn)行的線程數(shù)量
"""
"""
def func():
	time.sleep(1)
if __name__ == "__main__":
	t = Thread(target=func)
	t.start()
	# 檢測(cè)線程是否仍然存在
	print( t.is_alive() )
	# 線程.getName()     獲取線程名字
	print(t.getName())
	# 設(shè)置線程名字
	t.setName("抓API接口")
	print(t.getName())
"""
from threading import currentThread
from threading import enumerate
from threading import activeCount
def func():
	time.sleep(0.1)
	print("當(dāng)前子線程號(hào)id是{},進(jìn)程號(hào){}".format( currentThread().ident ,os.getpid()) )
if __name__ == "__main__":
	t = Thread(target=func)
	t.start()
	print("當(dāng)前主線程號(hào)id是{},進(jìn)程號(hào){}".format( currentThread().ident ,os.getpid()) )
	for i in range(5):
		t = Thread(target=func)
		t.start()
	# 返回目前正在運(yùn)行的線程列表
	lst = enumerate()
	print(lst,len(lst))
	# 返回目前正在運(yùn)行的線程數(shù)量 (了解)
	print(activeCount())

3.2 守護(hù)線程

# ### 守護(hù)線程 : 等待所有線程全部執(zhí)行完畢之后,自己在終止程序,守護(hù)所有線程
from threading import Thread
import time
def func1():
	while True:
		time.sleep(1)		
		print("我是函數(shù)func1")
def func2():
	print("我是func2  start ... ")
	time.sleep(3)
	print("我是func2  end ... ")
def func3():
	print("我是func3 start ... ")
	time.sleep(6)	
	print("我是func3  end ... ")
if __name__ == "__main__":
	t = Thread(target=func1)
	t2 = Thread(target=func2)
	t3 = Thread(target=func3)
	# 設(shè)置守護(hù)線程 (啟動(dòng)前設(shè)置)
	t.setDaemon(True)
	t.start()
	t2.start()
	t3.start()
	print("主線程執(zhí)行結(jié)束.... ")

4. 線程安全問(wèn)題

4.1 線程安全問(wèn)題

# ### 線程中的數(shù)據(jù)安全問(wèn)題
from threading import  Thread  , Lock
import time
n = 0
def func1(lock):
	global n
	lock.acquire() 
	for i in range(1000000):		
		n += 1
	lock.release()
def func2(lock):
	global n
	# with語(yǔ)法可以簡(jiǎn)化上鎖+解鎖的操作,自動(dòng)完成
	with lock:
		for i in range(1000000):
			n -= 1
if __name__ == "__main__":
	lst = []
	lock = Lock()
	start = time.time()
	for i in range(10):
		t1 = Thread(target=func1 ,args=(lock,) )
		t1.start()
		t2 = Thread(target=func2 ,args=(lock,) )
		t2.start()
		lst.append(t1)
		lst.append(t2)
	for i in lst:
		i.join()
	# print(lst,len(lst))
	end = time.time()
	print("主線程執(zhí)行結(jié)束... 當(dāng)前n結(jié)果為{} ,用時(shí){}".format(n , end-start))

4.2 Semaphore_信號(hào)量

# ### 信號(hào)量 Semaphore (線程)
"""同一時(shí)間對(duì)多個(gè)線程上多把鎖"""
from threading import Thread,Semaphore
import time , random
def func(i,sem):
	time.sleep(random.uniform(0.1,0.7))
	# with語(yǔ)法自動(dòng)實(shí)現(xiàn)上鎖 + 解鎖
	with sem:		
		print("我在電影院拉屎 .... 我是{}號(hào)".format(i))
if __name__ == "__main__":
	sem = Semaphore(5)
	for i in range(30):
		Thread(target=func,args=(i,sem)).start()
	print(1)
"""
	創(chuàng)建線程是異步的,
	上鎖的過(guò)程會(huì)導(dǎo)致程序變成同步;
"""		

5. 死鎖_互斥鎖_遞歸鎖

加一把鎖,就對(duì)應(yīng)解一把鎖.形成互斥鎖.
從語(yǔ)法上來(lái)說(shuō),鎖可以互相嵌套,但不要使用,
不要因?yàn)檫壿媶?wèn)題讓上鎖分成兩次.導(dǎo)致死鎖
遞歸鎖用于解決死鎖,但只是一種應(yīng)急的處理辦法
# ### 互斥鎖 死鎖 遞歸鎖
from threading import Thread , Lock , RLock
import time
# (1) 語(yǔ)法上的死鎖
"""語(yǔ)法上的死鎖: 是連續(xù)上鎖不解鎖"""
"""
lock = Lock()
lock.acquire()
# lock.acquire() error
print("代碼執(zhí)行中 ... 1")
lock.release()
lock.release()
"""
"""是兩把完全不同的鎖"""
lock1 = Lock()
lock2 = Lock()
lock1.acquire()
lock2.acquire()
print("代碼執(zhí)行中 ... 2")
lock2.release()
lock1.release()
# (2) 邏輯上的死鎖
""""""
noodles_lock = Lock()
kuaizi_lock = Lock()
def eat1(name):
	noodles_lock.acquire()
	print("{}搶到面條了 ... ".format(name))
	kuaizi_lock.acquire()
	print("{}搶到筷子了 ... ".format(name))
	print("開(kāi)始享受香菇青菜面 ... ")
	time.sleep(0.5)
	kuaizi_lock.release()
	print("{}吃完了,滿意的放下了筷子".format(name))
	noodles_lock.release()
	print("{}吃完了,滿意的放下了面條".format(name))
def eat2(name):
	kuaizi_lock.acquire()
	print("{}搶到筷子了 ... ".format(name))
	noodles_lock.acquire()
	print("{}搶到面條了 ... ".format(name))
	print("開(kāi)始享受香菇青菜面 ... ")
	time.sleep(0.5)	
	noodles_lock.release()
	print("{}吃完了,滿意的放下了面條".format(name))
	# kuaizi_lock.release()
	print("{}吃完了,滿意的放下了筷子".format(name))
if __name__ == "__main__":
	lst1 = ["康???,"張宇"]
	lst2 = ["張保張","趙沈陽(yáng)"]
	for name in lst1:
		Thread(target=eat1,args=(name,)).start()
	for name in lst2:
		Thread(target=eat2,args=(name,)).start()
# (3) 使用遞歸鎖
"""
	遞歸鎖的提出專門(mén)用來(lái)解決死鎖現(xiàn)象
	用于快速解決線上項(xiàng)目死鎖問(wèn)題
	即使連續(xù)上鎖,使用遞歸鎖后也形同虛設(shè),因?yàn)檫f歸鎖的作用在于解鎖;
"""
"""
# 基本語(yǔ)法
rlock = RLock()
rlock.acquire()
rlock.acquire()
rlock.acquire()
rlock.acquire()
print("代碼執(zhí)行中 ... 3")
rlock.release()
rlock.release()
rlock.release()
rlock.release()
"""
"""
noodles_lock = Lock()
kuaizi_lock = Lock()
# 讓noodles_lock和kuaizi_lock 都等于遞歸鎖
noodles_lock = kuaizi_lock = RLock()
def eat1(name):
	noodles_lock.acquire()
	print("{}搶到面條了 ... ".format(name))
	kuaizi_lock.acquire()
	print("{}搶到筷子了 ... ".format(name))
	print("開(kāi)始享受香菇青菜面 ... ")
	time.sleep(0.5)
	kuaizi_lock.release()
	print("{}吃完了,滿意的放下了筷子".format(name))
	noodles_lock.release()
	print("{}吃完了,滿意的放下了面條".format(name))
def eat2(name):
	kuaizi_lock.acquire()
	print("{}搶到筷子了 ... ".format(name))
	noodles_lock.acquire()
	print("{}搶到面條了 ... ".format(name))
	print("開(kāi)始享受香菇青菜面 ... ")
	time.sleep(0.5)	
	noodles_lock.release()
	print("{}吃完了,滿意的放下了筷子".format(name))
	kuaizi_lock.release()
	print("{}吃完了,滿意的放下了筷子".format(name))
if __name__ == "__main__":
	lst1 = ["康???,"張宇"]
	lst2 = ["張保張","趙沈陽(yáng)"]
	for name in lst1:
		Thread(target=eat1,args=(name,)).start()
	for name in lst2:
		Thread(target=eat2,args=(name,)).start()
"""
# (4) 盡量使用一把鎖解決問(wèn)題,(少用鎖嵌套,容易邏輯死鎖)
"""
lock = Lock()
def eat1(name):
	lock.acquire()
	print("{}搶到面條了 ... ".format(name))
	print("{}搶到筷子了 ... ".format(name))
	print("開(kāi)始享受香菇青菜面 ... ")
	time.sleep(0.5)	
	print("{}吃完了,滿意的放下了筷子".format(name))	
	print("{}吃完了,滿意的放下了面條".format(name))
	lock.release()
def eat2(name):
	lock.acquire()
	print("{}搶到筷子了 ... ".format(name))
	print("{}搶到面條了 ... ".format(name))
	print("開(kāi)始享受香菇青菜面 ... ")
	time.sleep(0.5)	
	print("{}吃完了,滿意的放下了筷子".format(name))
	print("{}吃完了,滿意的放下了筷子".format(name))
	lock.release()
if __name__ == "__main__":
	lst1 = ["康???,"張宇"]
	lst2 = ["張保張","趙沈陽(yáng)"]
	for name in lst1:
		Thread(target=eat1,args=(name,)).start()
	for name in lst2:
		Thread(target=eat2,args=(name,)).start()
"""

6. 線程事件

# ### 事件 Event
from threading import Thread , Event
import time,random
"""
wait   : 動(dòng)態(tài)加阻塞 (True => 放行  False => 阻塞)
is_set : 獲取內(nèi)部成員屬性值是True 還是 False
set    : 把False -> True
clear  : 把True  -> False
"""
# (1) 基本語(yǔ)法
"""
e = Event()
print(e.is_set())
e.set()
print(e.is_set())
e.wait()
e.clear()
# 最多阻塞三秒,放行
e.wait(3)
print("代碼執(zhí)行中 ... ")
"""
# (2) 模擬連接遠(yuǎn)程數(shù)據(jù)庫(kù)
"""最多連接三次,如果三次都連接不上,直接報(bào)錯(cuò)."""
def check(e):	
	print("目前正在檢測(cè)您的賬號(hào)和密碼 .... ")
	# 模擬延遲的場(chǎng)景
	time.sleep(random.randrange(1,7)) # 1 ~ 6
	# 把成員屬性值從False -> True
	e.set()
def connect(e):
	sign = False
	for i in range(1,4):
		e.wait(1)
		if e.is_set():
			print("數(shù)據(jù)庫(kù)連接成功 ... ")
			sign = True
			break
		else:
			print("嘗試連接數(shù)據(jù)庫(kù)第{}次失敗了...".format(i))
	# 三次都不成功,報(bào)錯(cuò)
	if sign == False:
		# 主動(dòng)拋出異常  超時(shí)錯(cuò)誤
		raise TimeoutError
# if __name__ == "__main__":
e = Event()
t1 = Thread(target=check,args=(e,))
t1.start()
t2 = Thread(target=connect,args=(e,))
t2.start()

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Selenium中的option使用示例

    Selenium中的option使用示例

    這篇文章主要介紹了Selenium中的option用法實(shí)例,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • 教你python制作自己的模塊的基本步驟

    教你python制作自己的模塊的基本步驟

    這篇文章主要介紹了python如何制作自己的模塊,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • python六種基本數(shù)據(jù)類型及常用函數(shù)展示

    python六種基本數(shù)據(jù)類型及常用函數(shù)展示

    這篇文章主要為大家介紹了python六種基本數(shù)據(jù)類型及常用函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-11-11
  • Python Pandas Dataframe.describe()使用及代碼實(shí)例

    Python Pandas Dataframe.describe()使用及代碼實(shí)例

    這篇文章主要介紹了Python Pandas Dataframe.describe()使用及代碼實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 簡(jiǎn)析Python的閉包和裝飾器

    簡(jiǎn)析Python的閉包和裝飾器

    這篇文章主要為大家詳細(xì)介紹了Python的閉包和裝飾器,何為閉包?何為裝飾器?感興趣的小伙伴們可以參考一下
    2016-02-02
  • Python用二分法求平方根的案例

    Python用二分法求平方根的案例

    這篇文章主要介紹了Python用二分法求平方根的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • 利用Python檢測(cè)URL狀態(tài)

    利用Python檢測(cè)URL狀態(tài)

    最近小編接到這樣的需求,Python檢測(cè)URL狀態(tài),并追加保存200的URL。接下來(lái)通過(guò)實(shí)例代碼給大家分析講解,需要的朋友跟隨小編一起看看吧
    2019-07-07
  • Python入門(mén)教程(十四)Python的集合

    Python入門(mén)教程(十四)Python的集合

    這篇文章主要介紹了Python入門(mén)教程(十四)Python的集合,Python是一門(mén)非常強(qiáng)大好用的語(yǔ)言,也有著易上手的特性,本文為入門(mén)教程,需要的朋友可以參考下
    2023-04-04
  • 一文帶你搞懂Python中的文件操作

    一文帶你搞懂Python中的文件操作

    這篇文章主要為大家詳細(xì)介紹了Python中常見(jiàn)的文件操作的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python有一定的幫助,感興趣的可以了解一下
    2022-11-11
  • python使用Matplotlib畫(huà)條形圖

    python使用Matplotlib畫(huà)條形圖

    這篇文章主要為大家詳細(xì)介紹了python使用Matplotlib畫(huà)條形圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09

最新評(píng)論