目錄
- 一、python線程模塊的選擇
- 二、threading模塊
-
三、通過threading.Thread類創建線程
- 3.1 創建線程的方式一
- 3.2 創建線程的方式二
-
四、多線程與多進程
- 4.1 pid的比較
- 4.2 開啟效率的較量
- 4.3 內存數據的共享問題
-
五、Thread類的其他方法
- 5.1 代碼示例
- 5.2 join方法
-
六、多線程實現socket
- 6.1 服務端
- 6.2 客戶端
一、python線程模塊的選擇
Python提供了幾個用于多線程編程的模塊, 包括thread、threading和Queue等。 thread和threading模塊允許程序員創建和管理線程。thread模塊提供了基本的線程和鎖的支持,threading提供了更高級別、功能更強的線程管理的功能。Queue模塊允許用戶創建一個可以用于多個線程之間共享數據的隊列數據結構。
避免使用thread模塊,因為更高級別的threading模塊更為先進,對線程的支持更為完善,而且使用thread模塊里的屬性有可能會與threading出現沖突;其次低級別的thread模塊的同步原語很少(實際上只有一個),而threading模塊則有很多;再者,thread模塊中當主線程結束時,所有的線程都會被強制結束掉,沒有警告也不會有正常的清除工作, 至少threading模塊能確保重要的子線程退出后進程才退出。
thread模塊不支持守護線程, 當主線程退出時,所有的子線程不論它們是否還在工作,都會被強行退出。而threading模塊支持守護線程,守護線程一般是一個等待客戶請求的服務器,如果沒有客戶提出請求它就在那等著,如果設定一個線程為守護線程,就表示這個線程是不重要的,在進程退出的時候,不用等待這個線程退出。
二、threading模塊
multiprocess模塊的完全模仿了threading模塊的接口,二者在使用層面,有很大的相似性,因而不再詳細介紹(官方鏈接)
三、通過threading.Thread類創建線程
3.1 創建線程的方式一
from threading import Thread
import time
def sayhi(name):
time.sleep(2)
print('%s say hello' %name)
if __name__ == '__main__':
t=Thread(target=sayhi,args=('nick',))
t.start()
print('主線程')
3.2 創建線程的方式二
from threading import Thread
import time
class Sayhi(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
time.sleep(2)
print('%s say hello' % self.name)
if __name__ == '__main__':
t = Sayhi('nick')
t.start()
print('主線程')
四、多線程與多進程
4.1 pid的比較
from threading import Thread
from multiprocessing import Process
import os
def work():
print('hello',os.getpid())
if __name__ == '__main__':
# part1:在主進程下開啟多個線程,每個線程都跟主進程的pid一樣
t1=Thread(target=work)
t2=Thread(target=work)
t1.start()
t2.start()
print('主線程/主進程pid',os.getpid())
# part2:開多個進程,每個進程都有不同的pid
p1=Process(target=work)
p2=Process(target=work)
p1.start()
p2.start()
print('主線程/主進程pid',os.getpid())
4.2 開啟效率的較量
from threading import Thread
from multiprocessing import Process
import os
def work():
print('hello')
if __name__ == '__main__':
# 在主進程下開啟線程
t=Thread(target=work)
t.start()
print('主線程/主進程')
'''
打印結果:
hello
主線程/主進程
'''
# 在主進程下開啟子進程
t=Process(target=work)
t.start()
print('主線程/主進程')
'''
打印結果:
主線程/主進程
hello
'''
4.3 內存數據的共享問題
from threading import Thread
from multiprocessing import Process
import os
def work():
global n
n=0
if __name__ == '__main__':
# n=100
# p=Process(target=work)
# p.start()
# p.join()
# print('主',n) # 毫無疑問子進程p已經將自己的全局的n改成了0,但改的僅僅是它自己的,查看父進程的n仍然為100
n=1
t=Thread(target=work)
t.start()
t.join()
print('主',n) # 查看結果為0,因為同一進程內的線程之間共享進程內的數據
五、Thread類的其他方法
Thread實例對象的方法:
-
isAlive()
:返回線程是否活動的。 -
getName()
:返回線程名。 -
setName()
:設置線程名。
threading模塊提供的一些方法:
-
threading.currentThread()
:返回當前的線程變量。 -
threading.enumerate()
:返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。 -
threading.activeCount()
:返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
5.1 代碼示例
from threading import Thread
import threading
from multiprocessing import Process
import os
def work():
import time
time.sleep(3)
print(threading.current_thread().getName())
if __name__ == '__main__':
# 在主進程下開啟線程
t=Thread(target=work)
t.start()
print(threading.current_thread().getName())
print(threading.current_thread()) # 主線程
print(threading.enumerate()) # 連同主線程在內有兩個運行的線程
print(threading.active_count())
print('主線程/主進程')
'''
打印結果:
MainThread
<_MainThread(MainThread, started 140735268892672)>
[<_MainThread(MainThread, started 140735268892672)>,
]
主線程/主進程
Thread-1
'''
5.2 join方法
from threading import Thread
import time
def sayhi(name):
time.sleep(2)
print('%s say hello' %name)
if __name__ == '__main__':
t=Thread(target=sayhi,args=('nick',))
t.start()
t.join()
print('主線程')
print(t.is_alive())
'''
nick say hello
主線程
False
'''
六、多線程實現socket
6.1 服務端
import multiprocessing
import threading
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',8080))
s.listen(5)
def action(conn):
while True:
data=conn.recv(1024)
print(data)
conn.send(data.upper())
if __name__ == '__main__':
while True:
conn,addr=s.accept()
p=threading.Thread(target=action,args=(conn,))
p.start()
6.2 客戶端
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',8080))
while True:
msg=input('>>: ').strip()
if not msg:continue
s.send(msg.encode('utf-8'))
data=s.recv(1024)
print(data)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
