Python中使用線程有兩種方式:函數或者用類來包裝線程對象。
函數式:調用thread模塊中的start_new_thread()函數來產生新線程。語法如下:
thread.start_new_thread ( function, args[, kwargs] )
參數說明:
- function - 線程函數。
- args - 傳遞給線程函數的參數,他必須是個tuple類型。
- kwargs - 可選參數。
# -*- coding: UTF-8 -*-
import thread
import time
# 爲線程定義一個函數
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )
# 創建兩個線程
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
# -*- coding: UTF-8 -*-
import thread
import time
# 爲線程定義一個函數
class Test(object):
def print_time(self, threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )
test = Test()
# 創建兩個線程
try:
thread.start_new_thread( test.print_time, ("Thread-1", 2) )
thread.start_new_thread( test.print_time, ("Thread-2", 4) )
except:
print "Error: unable to start thread"
while 1:
pass
執行以上程序輸出結果如下:
Thread-1: Fri Mar 03 20:36:49 2017
Thread-2: Fri Mar 03 20:36:49 2017
Thread-1: Fri Mar 03 20:36:49 2017
Thread-1: Fri Mar 03 20:36:49 2017
Thread-2: Fri Mar 03 20:36:49 2017
Thread-1: Fri Mar 03 20:36:49 2017
Thread-1: Fri Mar 03 20:36:49 2017
Thread-2: Fri Mar 03 20:36:50 2017
Thread-2: Fri Mar 03 20:36:50 2017
Thread-2: Fri Mar 03 20:36:50 2017
線程的結束一般依靠線程函數的自然結束;也可以在線程函數中調用thread.exit(),他拋出SystemExit exception,達到退出線程的目的。
線程模塊
Python通過兩個標準庫thread和threading提供對線程的支持。thread提供了低級別的、原始的線程以及一個簡單的鎖。
thread 模塊提供的其他方法:
- threading.currentThread(): 返回當前的線程變量。
- threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啓動後、結束前,不包括啓動前和終止後的線程。
- threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
除了使用方法外,線程模塊同樣提供了Thread類來處理線程,Thread類提供了以下方法:
- run(): 用以表示線程活動的方法。
-
start():啓動線程活動。
- join([time]): 等待至線程中止。這阻塞調用線程直至線程的join() 方法被調用中止-正常退出或者拋出未處理的異常-或者是可選的超時發生。
- isAlive(): 返回線程是否活動的。
- getName(): 返回線程名。
- setName(): 設置線程名。
使用Threading模塊創建線程
使用Threading模塊創建線程,直接從threading.Thread繼承,然後重寫__init__方法和run方法:
# -*- coding: UTF-8 -*-
import threading
import time
exitFlag = 0
class myThread (threading.Thread): #繼承父類threading.Thread
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self): #把要執行的代碼寫到run函數裏面 線程在創建後會直接運行run函數
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:
thread.exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# 創建新線程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 開啓線程
thread1.start()
thread2.start()
print "Exiting Main Thread"
以上程序執行結果如下;
Starting Thread-1Starting Thread-2
Exiting Main Thread
Thread-1: Fri Mar 03 20:46:52 2017
Thread-2: Fri Mar 03 20:46:53 2017
Thread-1: Fri Mar 03 20:46:53 2017
Thread-1: Fri Mar 03 20:46:54 2017
Thread-2: Fri Mar 03 20:46:55 2017
Thread-1: Fri Mar 03 20:46:55 2017
Thread-1: Fri Mar 03 20:46:56 2017
Exiting Thread-1
Thread-2: Fri Mar 03 20:46:57 2017
Thread-2: Fri Mar 03 20:46:59 2017
Thread-2: Fri Mar 03 20:47:01 2017
Exiting Thread-2
線程同步
如果多個線程共同對某個數據修改,則可能出現不可預料的結果,爲了保證數據的正確性,需要對多個線程進行同步。
使用Thread對象的Lock和Rlock可以實現簡單的線程同步,這兩個對象都有acquire方法和release方法,對於那些需要每次只允許一個線程操作的數據,可以將其操作放到acquire和release方法之間。
# -*- coding: UTF-8 -*-
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 "Starting " + self.name
# 獲得鎖,成功獲得鎖定後返回True
# 可選的timeout參數不填時將一直阻塞直到獲得鎖定
# 否則超時後將返回False
threadLock.acquire()
print_time(self.name, self.counter, 3)
# 釋放鎖
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 = []
# 創建新線程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 開啓新線程
thread1.start()
thread2.start()
# 添加線程到線程列表
threads.append(thread1)
threads.append(thread2)
# 等待所有線程完成
for t in threads:
t.join()
print "Exiting Main Thread"