同時運行多個線程類似于同時運行多個不同的程序,但具有以下好處 -
進程內(nèi)的多個線程與主線程共享相同的數(shù)據(jù)空間,因此可以比單獨的進程更容易地共享信息或彼此進行通信。
線程有時也被稱為輕量級進程,它們不需要太多的內(nèi)存開銷; 它們比進程便宜。
線程有一個開始,執(zhí)行順序和終止。 它有一個指令指針,可以跟蹤其上下文中當(dāng)前運行的位置。
有兩種不同的線程 -
內(nèi)核線程是操作系統(tǒng)的一部分,而用戶空間線程未在內(nèi)核中實現(xiàn)。
有兩個模塊用于支持在Python 3中使用線程 -
thread模塊已被“不推薦”了很長一段時間。 鼓勵用戶使用threading模塊。 因此,在Python 3中,thread模塊不再可用。 但是,thread模塊已被重命名為“_thread”,用于Python 3中的向后兼容性。
要產(chǎn)生/啟動一個線程,需要調(diào)用thread模塊中的以下方法 -
_thread.start_new_thread ( function, args[, kwargs] )
這種方法調(diào)用可以快速有效地在Linux和Windows中創(chuàng)建新的線程。
方法調(diào)用立即返回,子線程啟動并使用傳遞的args列表調(diào)用函數(shù)。當(dāng)函數(shù)返回時,線程終止。
在這里,args是一個元組的參數(shù); 使用空的元組來調(diào)用函數(shù)表示不傳遞任何參數(shù)。 kwargs是關(guān)鍵字參數(shù)的可選字典。
示例
#!/usr/bin/python3
import _thread
import time
# Define a function for the thread
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("%s: %s" % ( threadName, time.ctime(time.time()) ))
# Create two threads as follows
try:
_thread.start_new_thread( print_time, ("Thread-1", 2, ) )
_thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print ("Error: unable to start thread")
while 1:
pass
當(dāng)執(zhí)行上述代碼時,會產(chǎn)生以下結(jié)果 -
F:\worksp\python>python thread_start.py
Thread-1: Tue Jun 27 03:06:09 2018
Thread-2: Tue Jun 27 03:06:11 2018
Thread-1: Tue Jun 27 03:06:11 2018
Thread-1: Tue Jun 27 03:06:13 2018
Thread-2: Tue Jun 27 03:06:15 2018
Thread-1: Tue Jun 27 03:06:15 2018
程序進入無限循環(huán),可通過按ctrl-c停止或退出。雖然它對于低級線程非常有效,但與較新的線程模塊相比,thread模塊非常有限。
Python 2.4中包含的較新的線程模塊為線程提供了比上面討論的線程模塊更強大的高級支持。
線程模塊公開了線程模塊的所有方法,并提供了一些其他方法 -
threading.activeCount() - 返回活動的線程對象的數(shù)量。threading.currentThread() - 返回調(diào)用者線程控件中線程對象的數(shù)量。threading.enumerate() - 返回當(dāng)前處于活動狀態(tài)的所有線程對象的列表。除了這些方法之外,threading模塊還有實現(xiàn)線程的Thread類。 Thread類提供的方法如下:
run() - run()方法是線程的入口點。start() - start()方法通過調(diào)用run()方法啟動一個線程。join([time]) - join()等待線程終止。isAlive() - isAlive()方法檢查線程是否仍在執(zhí)行。getName() - getName()方法返回一個線程的名稱。setName() - setName()方法設(shè)置線程的名稱。要使用threading模塊實現(xiàn)新線程,必須執(zhí)行以下操作:
Thread類的新子類。__init __(self [,args])方法添加其他參數(shù)。run(self [,args])方法來實現(xiàn)線程在啟動時應(yīng)該執(zhí)行的操作。當(dāng)創(chuàng)建了新的Thread的子類之后,就可以創(chuàng)建一個實例,然后調(diào)用start()方法來調(diào)用run()方法來啟動一個新的線程。
示例
#!/usr/bin/python3
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 ("Starting " + self.name)
print_time(self.name, self.counter, 5)
print ("Exiting " + 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
# Create new threads
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exiting Main Thread")
當(dāng)運行上述程序時,它會產(chǎn)生以下結(jié)果 -
Starting Thread-1
Starting Thread-2
Thread-1: Tue Jun 27 03:19:43 2017
Thread-2: Tue Jun 27 03:19:44 2017
Thread-1: Tue Jun 27 03:19:44 2017
Thread-1: Tue Jun 27 03:19:45 2017
Thread-2: Tue Jun 27 03:19:46 2017
Thread-1: Tue Jun 27 03:19:46 2017
Thread-1: Tue Jun 27 03:19:47 2017
Exiting Thread-1
Thread-2: Tue Jun 27 03:19:48 2017
Thread-2: Tue Jun 27 03:19:50 2017
Thread-2: Tue Jun 27 03:19:52 2017
Exiting Thread-2
Exiting Main Thread
Python提供的threading模塊包括一個簡單易用的鎖定機制,允許同步線程。 通過調(diào)用lock()方法創(chuàng)建一個新的鎖,該方法返回新的鎖。
新鎖對象的acquire(blocking)方法用于強制線程同步運行??蛇x的blocking參數(shù)能夠控制線程是否要等待獲取鎖定。
如果blocking設(shè)置為0,則如果無法獲取鎖定,則線程將立即返回0值,如果鎖定已獲取,則線程返回1。 如果blocking設(shè)置為1,則線程將blocking并等待鎖定被釋放。
新的鎖定對象的release()方法用于在不再需要鎖定時釋放鎖。
示例
#!/usr/bin/python3
# save file : MyThread2.py
import threading
import time
class MyThread2 (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 ("Starting " + self.name)
# Get lock to synchronize threads
threadLock.acquire()
print_time(self.name, self.counter, 3)
# Free lock to release next thread
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 = []
# Create new threads
thread1 = MyThread2(1, "Thread-1", 1)
thread2 = MyThread2(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print ("Exiting Main Thread")
當(dāng)執(zhí)行上述代碼時,會產(chǎn)生以下結(jié)果 -
Starting Thread-1
Starting Thread-2
Thread-1: Tue Jun 27 03:51:45 2017
Thread-1: Tue Jun 27 03:51:46 2017
Thread-1: Tue Jun 27 03:51:47 2017
Thread-2: Tue Jun 27 03:51:49 2017
Thread-2: Tue Jun 27 03:51:51 2017
Thread-2: Tue Jun 27 03:51:53 2017
Exiting Main Thread
queue模塊允許創(chuàng)建一個新的隊列對象,可以容納特定數(shù)量的項目。 有以下方法來控制隊列 -
get() - get()從隊列中刪除并返回一個項目。put() - put()將項添加到隊列中。qsize() - qsize()返回當(dāng)前隊列中的項目數(shù)。empty() - 如果隊列為空,則empty()方法返回True; 否則返回False。full() - 如果隊列已滿,則full()方法返回True; 否則返回False。示例
#!/usr/bin/python3
#coding=utf-8
import queue
import threading
import time
exitFlag = 0
class MyQueue (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 ("Starting " + self.name)
process_data(self.name, self.q)
print ("Exiting " + 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
# Create new threads
for tName in threadList:
thread = MyQueue(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# Fill the queue
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
# Wait for queue to empty
while not workQueue.empty():
pass
# Notify threads it's time to exit
exitFlag = 1
# Wait for all threads to complete
for t in threads:
t.join()
print ("Exiting Main Thread")
當(dāng)執(zhí)行上述代碼時,會產(chǎn)生以下結(jié)果 -
Starting Thread-1
Starting Thread-2
Starting Thread-3
Thread-3 processing One
Thread-3 processing Two
Thread-3 processing Three
Thread-3 processing Four
Thread-3 processing Five
Exiting Thread-1
Exiting Thread-2
Exiting Thread-3
Exiting Main Thread