多線程 VS 多進程
- 程序: 一堆代碼以文本形式存入一個文檔
- 進程: 程序運行的一個狀態
- 包含地址空間,內存,數據債等
- 每一進程由自己完全獨立的運行環境,多進程共享數據是一個問題
- 線程
- 一個進程的獨立運行片段,一個進程可以由多個線程
- 輕量化的進程
- 一個進程的多個線程間共享數據和上下文運行環境
- 共享互斥問題
- 全局解釋器鎖(GIL)
- Python代碼的執行是由python虛擬機進行控制
- 在主循環中有切只有一個控制線程在執行
- Python包
- thread : 有問題,不好用,python3改成了_thread
- threading: 通行的包
- 案例01
'''
利用time函數,生產兩個函數
順序調用
計算總的運行時間
'''
import time
def loopl():
# ctime 得到當前時間
print('Statr loop l at : ', time.ctime())
# 睡眠多長時間,單位是秒
time.sleep(4)
print('End loop l at : ', time.ctime())
def loop2():
# ctime 得到當前時間
print('Start loop 2 at : ', time.ctime())
# 睡眠多長時間,單位是秒
time.sleep(2)
print('End loop 2 at : ', time.ctime())
def main():
print('Starting at : ', time.ctime())
loopl()
loop2()
print('All done at : ', time.ctime())
if __name__ == '__main__':
main()
Starting at : Sat Jun 30 14:35:17 2018
Statr loop l at : Sat Jun 30 14:35:17 2018
End loop l at : Sat Jun 30 14:35:21 2018
Start loop 2 at : Sat Jun 30 14:35:21 2018
End loop 2 at : Sat Jun 30 14:35:23 2018
All done at : Sat Jun 30 14:35:23 2018
啓用多線程
# -*- coding:utf-8 -*-
'''
利用time函數,生產兩個函數
順序調用
計算總的運行時間
'''
import time
import _thread as thread
def loopl():
# ctime 得到當前時間
print('Statr loop l at : ', time.ctime())
# 睡眠多長時間,單位是秒
time.sleep(4)
print('End loop l at : ', time.ctime())
def loop2():
# ctime 得到當前時間
print('Start loop 2 at : ', time.ctime())
# 睡眠多長時間,單位是秒
time.sleep(2)
print('End loop 2 at : ', time.ctime())
def main():
print('Starting at : ', time.ctime())
# 啓動多線程的意思是用多線程去執行某個函數
# 啓動多線程函數爲start_new_thread
# 參數兩個,一個是需要運行的函數名,第二個是函數的參數作爲元祖使用,爲空則使用空元祖
# 注意⚠️:如果函數只有一個參數,需要參數後有一個逗號
thread.start_new_thread(loopl, ())
thread.start_new_thread(loop2, ())
print('All done at : ', time.ctime())
if __name__ == '__main__':
main()
time.sleep(5)
Starting at : Sat Jun 30 14:55:11 2018
All done at : Sat Jun 30 14:55:11 2018
Start loop 2 at : Sat Jun 30 14:55:11 2018
Statr loop l at : Sat Jun 30 14:55:11 2018
End loop 2 at : Sat Jun 30 14:55:13 2018
End loop l at : Sat Jun 30 14:55:15 2018
帶參數的函數,多線程執行例子
# -*- coding:utf-8 -*-
'''
利用time函數,生產兩個函數
順序調用
計算總的運行時間
'''
import time
import _thread as thread
def loopl(param):
# ctime 得到當前時間
print('Statr loop l at : ', time.ctime())
# 打印傳入參數
print("參數 param is :" + param)
# 睡眠多長時間,單位是秒
time.sleep(4)
print('End loop l at : ', time.ctime())
def loop2(name, name2):
# ctime 得到當前時間
print('Start loop 2 at : ', time.ctime())
# 打印參數
print("姓名1:" + name, "姓名2 :", name2)
# 睡眠多長時間,單位是秒
time.sleep(2)
print('End loop 2 at : ', time.ctime())
def main():
print('Starting at : ', time.ctime())
# 啓動多線程的意思是用多線程去執行某個函數
# 啓動多線程函數爲start_new_thread
# 參數兩個,一個是需要運行的函數名,第二個是函數的參數作爲元祖使用,爲空則使用空元祖
# 注意⚠️:如果函數只有一個參數,需要參數後有一個逗號
thread.start_new_thread(loopl, ("今天天氣不錯",))
thread.start_new_thread(loop2, ("王大拿","王呵呵"))
print('All done at : ', time.ctime())
if __name__ == '__main__':
main()
# 一定要有while語句,不然主線程結束,子線程也結束
#while True:
time.sleep(5)
threading的使用
- 直接利用threading.Thread生成Thread實例
- t = threading.Thread(target=xxx,args=(xxx,))
- t.statr(): 啓動多線程
- t.join(): 等待多線程執行完成
# -*- coding:utf-8 -*-
'''
利用time函數,生產兩個函數
順序調用
計算總的運行時間
'''
import time
import threading
def loopl(param):
# ctime 得到當前時間
print('Statr loop l at : ', time.ctime())
# 打印傳入參數
print("參數 param is :" + param)
# 睡眠多長時間,單位是秒
time.sleep(4)
print('End loop l at : ', time.ctime())
def loop2(name, name2):
# ctime 得到當前時間
print('Start loop 2 at : ', time.ctime())
# 打印參數
print("姓名1:" + name, "姓名2 :", name2)
# 睡眠多長時間,單位是秒
time.sleep(2)
print('End loop 2 at : ', time.ctime())
def main():
print('Starting at : ', time.ctime())
# 啓動多線程的意思是用多線程去執行某個函數
# 參數兩個,一個是需要運行的函數名,第二個是函數的參數作爲元祖使用,爲空則使用空元祖
# 注意⚠️:如果函數只有一個參數,需要參數後有一個逗號
t1 = threading.Thread(target=loopl, args=("老王頭",))
t1.start()
t2 = threading.Thread(target=loop2, args=("張芃芃", "李冬面",))
t2.start()
print('All done at : ', time.ctime())
if __name__ == '__main__':
main()
Starting at : Sat Jun 30 15:11:00 2018
Statr loop l at : Sat Jun 30 15:11:00 2018
參數 param is :老王頭
Start loop 2 at : All done at : Sat Jun 30 15:11:00 2018
Sat Jun 30 15:11:00 2018
姓名1:張芃芃 姓名2 : 李冬面
End loop 2 at : Sat Jun 30 15:11:02 2018
End loop l at : Sat Jun 30 15:11:04 2018
JOIN()用法
- join等線程執行完成後繼續往下執行
# -*- coding:utf-8 -*-
'''
利用time函數,生產兩個函數
順序調用
計算總的運行時間
'''
import time
import threading
def loopl(param):
# ctime 得到當前時間
print('Statr loop l at : ', time.ctime())
# 打印傳入參數
print("參數 param is :" + param)
# 睡眠多長時間,單位是秒
time.sleep(4)
print('End loop l at : ', time.ctime())
def loop2(name, name2):
# ctime 得到當前時間
print('Start loop 2 at : ', time.ctime())
# 打印參數
print("姓名1:" + name, "姓名2 :", name2)
# 睡眠多長時間,單位是秒
time.sleep(2)
print('End loop 2 at : ', time.ctime())
def main():
print('Starting at : ', time.ctime())
# 啓動多線程的意思是用多線程去執行某個函數
# 參數兩個,一個是需要運行的函數名,第二個是函數的參數作爲元祖使用,爲空則使用空元祖
# 注意⚠️:如果函數只有一個參數,需要參數後有一個逗號
t1 = threading.Thread(target=loopl, args=("老王頭",))
t1.start()
t2 = threading.Thread(target=loop2, args=("張芃芃", "李冬面",))
t2.start()
# 等待兩個線程都執行完畢,才繼續往下執行
t1.join()
t2.join()
print('All done at : ', time.ctime())
if __name__ == '__main__':
main()
守護線程
- 如果在程序中將子線程設置成守護線程,則子線程會在主線程結束的時候自動退出
- 一般認爲,守護線程不重要或者不運行離開主線程獨立運行
- 守護線程案例能否有效果跟環境相關
# 非守護線程例子
# -*- coding:utf-8 -*-
import time
import threading
def fun():
print("Strat fun")
time.sleep(2)
print("End fun")
print("Main thread")
t1 = threading.Thread(target=fun, args=())
t1.start()
time.sleep(1)
print("Main thread end")
Main thread
Strat fun
Main thread end
End fun
# 守護線程例子
# -*- coding:utf-8 -*-
import time
import threading
def fun():
print("Strat fun")
time.sleep(2)
print("End fun")
print("Main thread")
t1 = threading.Thread(target=fun, args=())
# 使用守護線程的方法,必須在start之前設置,否則無效
t1.setDaemon(True)
t1.start()
time.sleep(1)
print("Main thread end")
Main thread
Strat fun
Main thread end
End fun
線程常用屬性
- threading.currentThread: 返回當前線程變量
- threading.enumerate: 返回一個包含正在運行的線程list,正在運行的線程指的是線程啓動後,結束前的線程
- threading.activeCount: 返回正在運行的線程數量
- thr.setName: 設置線程名稱
- thr.getName: 獲取線程名稱
# -*- coding:utf-8 -*-
'''
利用time函數,生產兩個函數
順序調用
計算總的運行時間
'''
import time
import threading
def loopl(param):
# ctime 得到當前時間
print('Statr loop l at : ', time.ctime())
# 打印傳入參數
print("參數 param is :" + param)
# 睡眠多長時間,單位是秒
time.sleep(4)
print('End loop l at : ', time.ctime())
def loop2(name, name2):
# ctime 得到當前時間
print('Start loop 2 at : ', time.ctime())
# 打印參數
print("姓名1:" + name, "姓名2 :", name2)
# 睡眠多長時間,單位是秒
time.sleep(2)
print('End loop 2 at : ', time.ctime())
def main():
print('Starting at : ', time.ctime())
t1 = threading.Thread(target=loopl, args=("老王頭",))
t1.setName("THR_1_loop1")
t1.start()
t2 = threading.Thread(target=loop2, args=("張芃芃", "李冬面",))
t2.setName("THR_2_loop2")
t2.start()
# 3秒後,線程2結束運行
time.sleep(3)
# enumerate 得到正在運行子線程,及子線程1
for thr in threading.enumerate():
print("正在運行的線程名字是: {0}".format(thr.getName()))
print("正在運行的子線程數量爲:{0}".format(threading.activeCount()))
print('All done at : ', time.ctime())
if __name__ == '__main__':
main()
Starting at : Sat Jun 30 15:39:41 2018
Statr loop l at : Sat Jun 30 15:39:41 2018
參數 param is :老王頭
Start loop 2 at : Sat Jun 30 15:39:41 2018
姓名1:張芃芃 姓名2 : 李冬面
End loop 2 at : Sat Jun 30 15:39:43 2018
正在運行的線程名字是: MainThread
正在運行的線程名字是: Thread-2
正在運行的線程名字是: Thread-3
正在運行的線程名字是: IPythonHistorySavingThread
正在運行的線程名字是: Thread-1
正在運行的線程名字是: THR_1_loop1
正在運行的子線程數量爲:6
All done at : Sat Jun 30 15:39:44 2018
End loop l at : Sat Jun 30 15:39:45 2018
直接繼承自threading.Thread
- 直接繼承Thread
- 重寫run()
- 類實例可以直接運行
普通寫法
# 直接繼承threading.Thread 重寫run方法
import threading
import time
class ThreadFunc(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global n, lock
time.sleep(1)
if lock.acquire():
print(n,self.name)
n, self.name
n += 1
lock.release()
if "__main__" == __name__:
n = 1
ThreadList = []
lock = threading.Lock()
for i in range(1, 200):
t = ThreadFunc()
ThreadList.append(t)
for t in ThreadList:
t.start()
for t in ThreadList:
t.join()
企業寫法
import threading
from time import sleep, ctime
loop = [4, 2]
class ThreadFunc:
def __init__(self, name):
self.name = name
def loop(self, nloop, nsec):
'''
:param nloop: loop函數的名稱
:param nsec: 系統休眠時間
:return:
'''
print("Start loop ", nloop, 'at ', ctime())
sleep(nsec)
print("Done loop ", nloop, 'at ', ctime())
def main():
print("Starting at ", ctime())
# ThreadFunc("loop").loop 跟以下兩個式子相當:
# t = ThreadFunc("loop")
# t.loop
# 以下t1 和 t2 的定義方式相等
t = ThreadFunc("loop")
t1 = threading.Thread(target=t.loop, args=('LOOP1', 4))
# 以下寫法更西方化,工業化
t2 = threading.Thread(target=ThreadFunc('loop').loop, args=('LOOP2', 2))
# 常見錯誤寫法
# t1 = threading.Thread(target=ThreadFunc('loop').loop(100,4))
# t2 = threading.Thread(target=ThreadFunc('loop').loop(100,2))
t1.start()
t2.start()
t1.join()
t2.join()
print("ALL done at ", ctime())
if __name__ == '__main__':
main()
Starting at Sat Jun 30 16:00:49 2018
Start loop LOOP1 at Sat Jun 30 16:00:49 2018
Start loop LOOP2 at Sat Jun 30 16:00:49 2018
Done loop LOOP2 at Sat Jun 30 16:00:51 2018
Done loop LOOP1 at Sat Jun 30 16:00:53 2018
ALL done at Sat Jun 30 16:00:53 2018