python 多執行緒程式設計
使用回撥方式
import time
def countdown(n):
while n > 0:
print(`T-minus`, n)
n -= 1
time.sleep(5)
# Create and launch a thread
from threading import Thread
t = Thread(target=countdown, args=(10,))
t.start()
把執行緒放入一個類
from threading import Thread
class CountdownTask:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self, n):
while self._running and n > 0:
print(`T-minus`, n)
n -= 1
time.sleep(5)
c = CountdownTask()
t = Thread(target=c.run, args=(10,))
t.start()
c.terminate() # Signal termination
t.join() # Wait for actual termination (if needed)
注意使用變數 self._running
退出執行緒的方式
使用繼承方式
from threading import Thread
class CountdownThread(Thread):
def __init__(self, n):
super().__init__()
self.n = n
def run(self):
while self.n > 0:
print(`T-minus`, self.n)
self.n -= 1
time.sleep(5)
c = CountdownThread(5)
c.start()
使用 Queue 進行執行緒間通訊
import Queue
import threading
import time
task_queue = Queue.Queue()
class ThreadTest(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
msg = self.queue.get()
print(msg)
time.sleep(0.1)
self.queue.task_done()
def main():
start = time.time()
# populate queue with data
for i in range(100):
task_queue.put("message")
# spawn a pool of threads, and pass them queue instance
for i in range(5):
t = ThreadTest(task_queue)
t.setDaemon(True)
t.start()
# wait on the queue until everything has been processed
task_queue.join()
print "Elapsed Time: {}".format(time.time() - start)
if __name__ == "__main__":
main()
setDaemon 設定為 True, run 函式中不需要退出,主執行緒結束後所有子執行緒退出
如果 setDaemon 設定為 False,則改為
def run(self):
while not self.queue.empty():
msg = self.queue.get()
print(msg)
time.sleep(0.1)
self.queue.task_done()
並且在主函式結束前 join 所有執行緒
注意
-
向佇列中新增資料項時並不會複製此資料項,執行緒間通訊實際上是線上程間傳遞物件引用。如果你擔心物件的共享狀態,那你最好只傳遞不可修改的資料結構(如:整型、字串或者元組)或者一個物件的深拷貝。
from queue import Queue from threading import Thread import copy # A thread that produces data def producer(out_q): while True: # Produce some data ... out_q.put(copy.deepcopy(data)) # A thread that consumes data def consumer(in_q): while True: # Get some data data = in_q.get() # Process the data ...
- q.qsize() , q.full() , q.empty() 等實用方法可以獲取一個佇列的當前大小和狀態。但要注意,這些方法都不是執行緒安全的。可能你對一個佇列使用 empty() 判斷出這個佇列為空,但同時另外一個執行緒可能已經向這個佇列中插入一個資料項。