網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
一、簡(jiǎn)介
Python中使用線(xiàn)程有兩種方式:函數(shù)或者用類(lèi)來(lái)包裝線(xiàn)程對(duì)象。
函數(shù)式:調(diào)用 _thread 模塊中的start_new_thread()函數(shù)來(lái)產(chǎn)生新線(xiàn)程。
參數(shù)說(shuō)明:
- function - 線(xiàn)程函數(shù)。
- args - 傳遞給線(xiàn)程函數(shù)的參數(shù),他必須是個(gè)tuple類(lèi)型。
- kwargs - 可選參數(shù)。
實(shí)例:
import _thread
import time
# 為線(xiàn)程定義一個(gè)函數(shù)
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("%s: %s" % ( threadName, time.ctime(time.time()) ))
# 創(chuàng)建兩個(gè)線(xiàn)程
try:
_thread.start_new_thread( print_time, ("Thread-1", 2, ) )
_thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print ("Error: 無(wú)法啟動(dòng)線(xiàn)程")
while 1:
pass
二、線(xiàn)程模塊
Python3 通過(guò)兩個(gè)標(biāo)準(zhǔn)庫(kù) _thread 和 threading 提供對(duì)線(xiàn)程的支持。
_thread 提供了低級(jí)別的、原始的線(xiàn)程以及一個(gè)簡(jiǎn)單的鎖,它相比于 threading 模塊的功能還是比較有限的。
threading 模塊除了包含 _thread 模塊中的所有方法外,還提供的其他方法:
- threading.currentThread(): 返回當(dāng)前的線(xiàn)程變量。
- threading.enumerate(): 返回一個(gè)包含正在運(yùn)行的線(xiàn)程的list。正在運(yùn)行指線(xiàn)程啟動(dòng)后、結(jié)束前,不包括啟動(dòng)前和終止后的線(xiàn)程。
- threading.activeCount(): 返回正在運(yùn)行的線(xiàn)程數(shù)量,與len(threading.enumerate())有相同的結(jié)果。
除了使用方法外,線(xiàn)程模塊同樣提供了Thread類(lèi)來(lái)處理線(xiàn)程,Thread類(lèi)提供了以下方法:
- run(): 用以表示線(xiàn)程活動(dòng)的方法。
- start():啟動(dòng)線(xiàn)程活動(dòng)。
- join([time]): 等待至線(xiàn)程中止。這阻塞調(diào)用線(xiàn)程直至線(xiàn)程的join() 方法被調(diào)用中止-正常退出或者拋出未處理的異常-或者是可選的超時(shí)發(fā)生。
- isAlive(): 返回線(xiàn)程是否活動(dòng)的。
- getName(): 返回線(xiàn)程名。
- setName(): 設(shè)置線(xiàn)程名。
三、使用 threading 模塊創(chuàng)建線(xiàn)程
可以通過(guò)直接從 threading.Thread 繼承創(chuàng)建一個(gè)新的子類(lèi),并實(shí)例化后調(diào)用 start() 方法啟動(dòng)新線(xiàn)程,即它調(diào)用了線(xiàn)程的 run() 方法:
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print ("開(kāi)始線(xiàn)程:" + self.name)
print_time(self.name, self.counter, 5)
print ("退出線(xiàn)程:" + self.name)
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
# 創(chuàng)建新線(xiàn)程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 開(kāi)啟新線(xiàn)程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主線(xiàn)程")
四、線(xiàn)程同步
如果多個(gè)線(xiàn)程共同對(duì)某個(gè)數(shù)據(jù)修改,則可能出現(xiàn)不可預(yù)料的結(jié)果,為了保證數(shù)據(jù)的正確性,需要對(duì)多個(gè)線(xiàn)程進(jìn)行同步。
使用 Thread 對(duì)象的 Lock 和 Rlock 可以實(shí)現(xiàn)簡(jiǎn)單的線(xiàn)程同步,這兩個(gè)對(duì)象都有 acquire 方法和 release 方法,對(duì)于那些需要每次只允許一個(gè)線(xiàn)程操作的數(shù)據(jù),可以將其操作放到 acquire 和 release 方法之間。
如下:
注意: 多線(xiàn)程的優(yōu)勢(shì)在于可以同時(shí)運(yùn)行多個(gè)任務(wù)(至少感覺(jué)起來(lái)是這樣)。但是當(dāng)線(xiàn)程需要共享數(shù)據(jù)時(shí),可能存在數(shù)據(jù)不同步的問(wèn)題。
考慮這樣一種情況:一個(gè)列表里所有元素都是0,線(xiàn)程"set"從后向前把所有元素改成1,而線(xiàn)程"print"負(fù)責(zé)從前往后讀取列表并打印。 那么,可能線(xiàn)程"set"開(kāi)始改的時(shí)候,線(xiàn)程"print"便來(lái)打印列表了,輸出就成了一半0一半1,這就是數(shù)據(jù)的不同步。為了避免這種情況,引入了鎖的概念。 鎖有兩種狀態(tài)——鎖定和未鎖定。每當(dāng)一個(gè)線(xiàn)程比如"set"要訪問(wèn)共享數(shù)據(jù)時(shí),必須先獲得鎖定;如果已經(jīng)有別的線(xiàn)程比如"print"獲得鎖定了,那么就讓線(xiàn)程"set"暫停,也就是同步阻塞;等到線(xiàn)程"print"訪問(wèn)完畢,釋放鎖以后,再讓線(xiàn)程"set"繼續(xù)。 經(jīng)過(guò)這樣的處理,打印列表時(shí)要么全部輸出0,要么全部輸出1,不會(huì)再出現(xiàn)一半0一半1的尷尬場(chǎng)面。
實(shí)例:
import threading
import time
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print ("開(kāi)啟線(xiàn)程: " + self.name)
# 獲取鎖,用于線(xiàn)程同步
threadLock.acquire()
print_time(self.name, self.counter, 3)
# 釋放鎖,開(kāi)啟下一個(gè)線(xiàn)程
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
threadLock = threading.Lock()
threads = []
# 創(chuàng)建新線(xiàn)程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 開(kāi)啟新線(xiàn)程
thread1.start()
thread2.start()
# 添加線(xiàn)程到線(xiàn)程列表
threads.append(thread1)
threads.append(thread2)
# 等待所有線(xiàn)程完成
for t in threads:
t.join()
print ("退出主線(xiàn)程")
五、線(xiàn)程優(yōu)先級(jí)隊(duì)列( Queue)
1、queue隊(duì)列
(1.python3中的隊(duì)列模塊是queue,不是Queue
(2.一般涉及到同步,多線(xiàn)程之類(lèi)用到隊(duì)列模塊
(3.定義了 queue.Queue 類(lèi),以及繼承它的 queue.LifoQueue 類(lèi) 和 queue.PriorityQueue 類(lèi) 和 queue.SimpleQueue 類(lèi)
(4.分別對(duì)應(yīng)隊(duì)列類(lèi)(FIFO先進(jìn)先出),LIFO后進(jìn)先出隊(duì)列類(lèi),優(yōu)先隊(duì)列,無(wú)邊界FIFO簡(jiǎn)單隊(duì)列類(lèi)
(5.還有兩個(gè)異常:隊(duì)滿(mǎn)和隊(duì)空
2、隊(duì)列queue公共方法
'''
學(xué)習(xí)中遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流群:711312441
尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)!
'''
import queue
#創(chuàng)建基本隊(duì)列
#queue.Queue(maxsize=0)創(chuàng)建一個(gè)隊(duì)列對(duì)象(隊(duì)列容量),若maxsize小于或者等于0,隊(duì)列大小沒(méi)有限制
Q=queue.Queue(10)
print(Q)
print(type(Q))
#1.基本方法
print(Q.queue)#查看隊(duì)列中所有元素
print(Q.qsize())#返回隊(duì)列的大小
print(Q.empty())#判斷隊(duì)空
print(Q.full())#判斷隊(duì)滿(mǎn)
#2.獲取隊(duì)列,0--5
#Queue.put(item,block = True,timeout = None )將對(duì)象放入隊(duì)列,阻塞調(diào)用(block=False拋異常),無(wú)等待時(shí)間
for i in range(5):
Q.put(i)
# Queue.put_nowait(item)相當(dāng)于 put(item, False).
#3.讀隊(duì)列,0--5
#Queue.get(block=True, timeout=None)讀出隊(duì)列的一個(gè)元素,阻塞調(diào)用,無(wú)等待時(shí)間
while not Q.empty():
print(Q.get())
# Queue.get_nowait()相當(dāng)于get(False).取數(shù)據(jù),如果沒(méi)數(shù)據(jù)拋queue.Empty異常
#4.另兩種涉及等待排隊(duì)任務(wù)的方法
# Queue.task_done()在完成一項(xiàng)工作后,向任務(wù)已經(jīng)完成的隊(duì)列發(fā)送一個(gè)信號(hào)
# Queue.join()阻止直到隊(duì)列中的所有項(xiàng)目都被獲取并處理。即等到隊(duì)列為空再執(zhí)行別的操作
3、其他
(1.LifoQueue: LIFO后進(jìn)先出
(2.PriorityQueue:優(yōu)先級(jí)隊(duì)列,如果數(shù)據(jù)元素不具有可比性,則可將數(shù)據(jù)包裝在忽略數(shù)據(jù)項(xiàng)的類(lèi)中,僅比較優(yōu)先級(jí)編號(hào)
(3.SimpleQueue:簡(jiǎn)單隊(duì)列,無(wú)跟蹤任務(wù)的功能
六、Queue詳細(xì)參數(shù)和用法實(shí)例
Queue 模塊中的常用方法:
- Queue.qsize() 返回隊(duì)列的大小
- Queue.empty() 如果隊(duì)列為空,返回True,反之False
- Queue.full() 如果隊(duì)列滿(mǎn)了,返回True,反之False
- Queue.full 與 maxsize 大小對(duì)應(yīng)
- Queue.get([block[, timeout]])獲取隊(duì)列,timeout等待時(shí)間
- Queue.get_nowait() 相當(dāng)Queue.get(False)
- Queue.put(item) 寫(xiě)入隊(duì)列,timeout等待時(shí)間
- Queue.put_nowait(item) 相當(dāng)Queue.put(item, False)
- Queue.task_done() 在完成一項(xiàng)工作之后,Queue.task_done()函數(shù)向任務(wù)已經(jīng)完成的隊(duì)列發(fā)送一個(gè)信號(hào)
- Queue.join() 實(shí)際上意味著等到隊(duì)列為空,再執(zhí)行別的操作
實(shí)例:
import queue
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print ("開(kāi)啟線(xiàn)程:" + self.name)
process_data(self.name, self.q)
print ("退出線(xiàn)程:" + self.name)
def process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print ("%s processing %s" % (threadName, data))
else:
queueLock.release()
time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1
# 創(chuàng)建新線(xiàn)程
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# 填充隊(duì)列
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
# 等待隊(duì)列清空
while not workQueue.empty():
pass
# 通知線(xiàn)程是時(shí)候退出
exitFlag = 1
# 等待所有線(xiàn)程完成
for t in threads:
t.join()
print ("退出主線(xiàn)程")
原文鏈接:https://blog.csdn.net/qdPython/article/details/127090416
相關(guān)推薦
- 2022-05-06 SQLite3+Qt開(kāi)發(fā):SQLite3簡(jiǎn)要介紹+在Qt5中使用步驟
- 2021-12-07 通過(guò)DBeaver連接Phoenix操作hbase的方法_數(shù)據(jù)庫(kù)其它
- 2022-10-26 Python?模擬死鎖的常見(jiàn)實(shí)例詳解_python
- 2022-01-29 win server 2008 web IIS部署asp.net程序后,CSS樣式錯(cuò)亂不顯示問(wèn)題
- 2022-05-28 Redis如何使用樂(lè)觀鎖(CAS)保證數(shù)據(jù)一致性_Redis
- 2022-05-04 分享3個(gè)非常實(shí)用的?Python?模塊_python
- 2022-09-26 Linux系統(tǒng)監(jiān)控(top,ps,netstat,kill命令),定時(shí)任務(wù),系統(tǒng)啟動(dòng)(系統(tǒng)的啟動(dòng)級(jí)別
- 2022-10-11 在NVIDIA Jetson Xavier NX上使用tensorflow-gpu
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支