【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 num
print(f"改变前num={num}")
num+=1
print(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)
@staticmethod
def work(sock):
while True:
data=sock.recv(1024)
if data.decode()=='':
break
print(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 time
def 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 = True
t1.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密集型操作