日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

Python多線(xiàn)程使用方法詳細(xì)講解_python

作者:Python熱愛(ài)者 ? 更新時(shí)間: 2022-11-23 編程語(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

欄目分類(lèi)
最近更新