1.threading模塊
threading模塊是眾多多線程管理模塊的其一,它能確保重要的子線程退出后進程才退出。
multiprocess模塊的完全模仿了threading模塊的接口,二者在使用層面,有很大的相似性,因而不再詳細介紹
2.創建線程的兩種方式
方式一:
from threading import Thread
import time
# 進程等待所有線程結束后才會結束
def func():
print('線程 start')
time.sleep(2)
print('線程 end')
if __name__ == '__main__':
t = Thread(target=func)
t.start() # 告訴操作系統開一個線程
print('主')
方式二:
from threading import Thread
import time
class Myt(Thread):
def run(self):
print('子線程 start')
time.sleep(2)
print('子線程 end')
t = Myt()
t.start()
print('主線程'
3.子進程和子線程pid的比較
from threading import Thread
from multiprocessing import Process
import os
def func():
print('hello',os.getpid())
if __name__ == '__main__':
# 在主進程開啟多個線程,每個線程都跟主進程pid一樣
t1 = Thread(target=func)
t2 = Thread(target=func)
t1.start()
t2.start()
print('主線程/主進程pid:',os.getpid())
# 開個多個子進程,每個進程都有不同的pid:
p1 = Process(target=func)
p2 = Process(target=func)
p1.start()
p2.start()
print('主線程/主進程pid:', os.getpid())
4.子線程內存數據共享問題
from threading import Thread
from multiprocessing import Process
def func():
global n
n = 0
if __name__ == '__main__':
# 子進程:
n = 100
p = Process(target=func)
p.start()
p.join()
print('主',n) # 毫無疑問子進程p已經將自己的n改成了全局的n,改成了0,但改的僅僅是它自己的,查看父進程的n仍然為100
# 子線程:
n = 1
t=Thread(target=func)
t.start()
t.join()
print('主',n) # 查看結果為,因為同一進程內的線程之間共享進程內的數據
5.線程的join方法
from threading import Thread
import time
def func(name,n):
print(f'{name} start')
time.sleep(n)
print(f'{name} end')
t1 =Thread(target=func,args=('線程1',1))
t2 =Thread(target=func,args=('線程2',2))
t3 =Thread(target=func,args=('線程3',3 ))
start = time.time()
t1.start()
t2.start()
t3.start()
t1.join() # 等待子線程運行結束
t2.join()
t3.join()
end = time.time() #
print(end-start) # 3.0060362
6.Thread類的其他方法
isAlive()
:返回線程是否活動的。getName()
:返回線程名。setName()
:設置線程名。
threading模塊提供的一些方法:
threading.currentThread()
:返回當前的線程變量。threading.enumerate()
:返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。threading.activeCount()
:返回正在運行的線程數量,與len(threading.enumerate()) 有相同的結果。
from threading import Thread,currentThread,enumerate,activeCount
import time
def task():
print('子線程 start')
time.sleep(2)
print('子線程 end')
print(enumerate())
# print(currentThread(),'子線程')
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task)
t1.start()
t2.start()
# print(t1.is_alive()) # True
# print(t1.getName()) # Thread-1
# print(t2.getName()) # Thread-2
# t1.setName('班長')
# print(t1.getName())
print(currentThread().name)
# print(enumerate()) # [<_MainThread(MainThread, started 1856)>, <Thread(Thread-1, started 6948)>, <Thread(Thread-2, started 3128)>]
print(activeCount()) # 3
# print(len(enumerate())) # 3
7.多線程實現socket
server服務端
import socket
from threading import Thread
s=socket.socket()
s.bind(('127.0.0.1',8080))
s.listen(5)
def run(conn):
while True:
try:
data = conn.recv(1024)
print(data)
conn.send(data.upper())
except Exception:
break
if __name__ == '__main__':
while True:
print('等待客戶端連接')
conn,addr = s.accept()
print(f'客服端{addr}連接成功')
t = Thread(target=run,args=(conn,))
t.start()
client客戶端
import socket
s = socket.socket()
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.decode('utf-8'))