【1】線程的概念
1.線程-->進程會得到一個內存地址,進程是資源分配的基本單位線程才是真正進程里處理數據與邏輯的東西進程---》被分配一定的資源線程---》利用進程資源處理數據與邏輯
【2】進程和線程關系:
進程與進程之間是競爭關系,競爭內存空間和資源線程和線程之間,協作關系,共同完成某個任務
【3】進程和線程開銷問題
進程 > 線程
原因:一個進程相當于一個工作車間一個線程只是一個進程里的流水線線程只是在進程已經申請有的資源上進行的處理
【4】進程和線程的區別
1. 線程共享創建它的進程的地址空間; 進程具有自己的地址空間。
2.線程可以直接訪問其進程的數據段; 進程具有其父進程數據段的副本。
3.線程可以直接與所在進程中的其他線程通信; 進程必須使用進程間通信與同級進程進行通信。
4.新線程很容易創建; 新進程需要復制父進程。
5.線程可以對同一進程的線程行使相當大的控制權。 進程只能控制子進程。
"""
# 創建線程---->多線程和多進程只有在阻塞的時候才能到別的地方去運行
"""
【5】創建線程的方式
方式一:
引入模塊,直接創建
from threading import Thread
def work():...
if __name__ == '__main__':t1=Thread(target=work)t1.start()
方式二:
繼承Thread類,重寫run方法
繼承了之后我的 New_Thread類他實例化的對象就是一個線程
from threading import Thread
class New_Thread(Thread):
?def __init__(self):super().__init__()def run(self):print("我是線程")
if __name__ == '__main__':t=New_Thread()t.start()
【6】多線程共享數據,多進程之間的數據是隔離開的
通過例子不難發現,線程中的數據,進行修改,在其他線程中會變
但是進程中的數據卻不會
from multiprocessing import Process
from threading import Thread
num=10
def work():# 由于在局部修改全局的變量,要對局部的該變量進行等級提升global numprint(f"改變前num={num}")num+=1print(f"改變后num={num}")
def main():for i in range(4):# thread=Thread(target=work)# thread.start()# thread.join()process=Process(target=work)process.start()process.join()print(f"當前num={num}")
if __name__ == '__main__':main()
【7】線程的查看的pid與ppid與進程的區別
線程的pid是他所屬的進程,因為都是由同一個進程開的線程,所以他的pid是相同的,ppid相同由于是一個主進程開的進程里的線程
每個進程有每個進程的不一樣的pid,但又相同的ppid
?
def work(name):print(f"當前{name}的pid={os.getpid()}")print(f"當前{name}的ppid={os.getppid()}")
def main():for i in range(2):# th=Thread(target=work,args=(f'線程{i+1}',))# th.start()# th.join()"""當前線程1的pid=13532當前線程1的ppid=2792當前線程2的pid=13532當前線程2的ppid=2792當前主進程的pid=13532"""p=Process(target=work,args=(f'進程{i+1}',))p.start()p.join()"""當前進程1的pid=10412當前進程1的ppid=11060當前進程2的pid=16796當前進程2的ppid=11060當前主進程的pid=11060"""print(f"當前主進程的pid={os.getpid()}")
if __name__ == '__main__':main()
【8】線程服務器并發
服務端
import socket
from socket import SOL_SOCKET,SO_REUSEADDR
from threading import Thread
?
?
class Server():def __init__(self):self.server=socket.socket()self.server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)self.server.bind(('127.0.0.1',8080))self.server.listen(5)@staticmethoddef work(sock):while True:data=sock.recv(1024)if data.decode()=='':breakprint(data.decode())sock.send(f"你好{data.decode()}".encode())def main(self):while True:sock,addr=self.server.accept()t=Thread(target=self.work,args=(sock,))t.start()#t.join()
if __name__ == '__main__':t=Server()t.main()
客戶端
import socket
client=socket.socket()
client.connect(('127.0.0.1',8080))
while True:msg=input("請輸入》》:")client.send(msg.encode())data=client.recv(1024)print(data.decode())
【9】守護線程
主線程結束運行后不會馬上結束,而是等待其他非守護子線程結束之后才會結束
守護子線程會跟著主線程一起死
例子
from threading import Thread
from multiprocessing import Process
import timedef foo():print(f' this is foo begin')time.sleep(1)print(f' this is foo end')def func():print(f' this is func begin')time.sleep(3)print(f' this is func end')def main():t1 = Thread(target=foo)t2 = Thread(target=func)t1.daemon = Truet1.start()t2.start()print(f' this is main')if __name__ == '__main__':main()# this is foo begin# this is func begin# this is main# this is foo end# this is func end
【十】多進程和多線程之間比較
多進程--》適合計算密集型操作
多線程--》適合IO密集型操作