進程
是由若干線程
組成的,一個進程至少有一個線程多任務
可以由多進程
完成,也可以由一個進程內的多線程
完成。- Python的線程是真正的
Posix Thread
,而不是模擬出來的線程。
為什么使用多線程
- 多進程和多線程都可以完
同時
執行多任務的功能- 創建進程的系統開銷非常大,是一種
重量級
的多任務方式- 進程間的內存空間是
相互獨立
的,數據不能共享
- 線程屬性某個進程,創建線程的系統開銷比較小,是一種
輕量級
的多任務方式- 線程間
共享
所屬進程的內存空間,數據可以共享
threading
模塊
Python提供了兩個線程模塊:
_thread
和threading
_thread
是低級模塊threading
是高級模塊(推薦使用)
使用threading模塊中的Thread類
- 實例演示
import time, threading
def loop(): # 新線程執行的代碼
print('thread %s is running...' % threading.current_thread().name)
n = 0
while n < 5:
n = n + 1
print('thread %s >>> %s' % (threading.current_thread().name, n))
time.sleep(1)
print('thread %s ended.' % threading.current_thread().name)
print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)
thread MainThread is running...
thread LoopThread is running...
thread LoopThread >>> 1
thread LoopThread >>> 2
thread LoopThread >>> 3
thread LoopThread >>> 4
thread LoopThread >>> 5
thread LoopThread ended.
thread MainThread ended.
- 任何進程都默認啟動一個線程,稱為
主線程
,主線程可以啟動子線程
current_thread()
函數,返回當前線程名,主線程名為MainThread
- 子線程名在創建時指定,如不指將自動命名為
Thread-1,Thread-2
…
查看線程數量
import threading
from time import sleep,ctime
def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)
def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)
if __name__ == '__main__':
print('---開始---:%s'%ctime())
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
while True:
length = len(threading.enumerate())
print('當前運行的線程數為:%d'%length)
if length<=1:
break
sleep(0.5)
---開始---:Mon Jan 7 22:49:59 2019
正在唱歌...0
正在跳舞...0
當前運行的線程數為:3
當前運行的線程數為:3
正在跳舞...1
正在唱歌...1
當前運行的線程數為:3
當前運行的線程數為:3
當前運行的線程數為:3
正在唱歌...2
正在跳舞...2
當前運行的線程數為:3
當前運行的線程數為:3
當前運行的線程數為:1
線程的封裝
為了體現
封裝性
,使用threading
模塊時,通常會定義一個子類,讓它繼承自threading.Thread
類,并重寫run
方法
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = "I'm "+self.name+' @ '+str(i) #name屬性中保存當前線程名
print(msg)
if __name__ == '__main__':
t = MyThread()
t.start()
I'm Thread-1 @ 0
I'm Thread-1 @ 1
I'm Thread-1 @ 2
threading.Thread
類中的run
方法,用于定義線程的功能函數,可以在自己的線程類中進行重寫
- 當
Thread
類的start
方法執行后,會在線程獲得運行資源時調用run
方法- 如果直接調用
run
方法,并不能啟多線程,而僅僅是一個單線程的程序
課堂練習
實現多線程版的素數計算
import threading
class MyThread(threading.Thread):
def __init__(self, beg, end): # 通過類的構造方法進行參數據傳遞
super(MyThread, self).__init__() # 要調用父類的構造方法來進行初始化
self.__beg = beg
self.__end = end
def __isPrime(self, n): # 可以將某些處理函數變為私有方法
for x in range(2, n):
if n % x == 0:
return False
else:
return True
def run(self): # 方法名不能改變,只重寫
for n in range(self.__beg, self.__end):
if self.__isPrime(n):
print('%s:%d是素數' % (threading.current_thread().name, n))
if __name__ == '__main__':
t1 = MyThread(3, 1001)
t2 = MyThread(1001, 2001)
t3 = MyThread(2001, 3001)
t1.start()
t2.start()
t3.start()
# t1.run() # 如果直接調用run方法,并不能啟多線程,而僅僅是一個單線程的程序
# t2.run()
# t3.run()
- end -