Python线程详解

一、 线程理论

		进程是资源单位
			进程相当于工厂的车间 进程负责给内部的线程提供相应的资源
		线程是执行单位
			线程相当于车间里面的流水线 线程负责执行真正的功能 
			多个线程就多个流水线都是在进程的资源空间内
		线程的特征:
			1.一个进程至少有一个线程(没有进程哪来的线程 程序(客户端)没有运行什么都没有)
			2.多进程与多线程的区别
				多进程	需要申请内存空间 需要拷贝全部代码 资源消耗大	数据间不能共享
				多线程	不需要申请内存空间 也不需要拷贝全部代码 资源消耗小 数据间可以共享

二、 创建线程的两种方式

		开设线程不需要完整拷贝代码 所以无论什么系统都不会出现反复操作的情况 
		也不需要在启动脚本中执行 但是为了兼容性和统一性 习惯在启动脚本中编写
	第一种方式
		from threading import Thread
		import time				# 导入线程模块
		
		def task(name):			# 设置函数
		    print(f'{name}正在运行')
		    time.sleep(3)		# 休眠三秒
		    print(f'{name}运行结束')
		
		if __name__ == '__main__':		# 设置运行脚本 兼容性提升 
		    t = Thread(target=task, args=('LebronJames',))
		    t.start()
		    print('主线程')
	
	第二种方式
		rom threading import Thread
		import time 
		
		class MyThread(Thread):
		    def __init__(self, name):
		        super().__init__()
		        self.name = name
		
		    def run(self):
		        print(f'{self.name}正在运行')
		        time.sleep(3)
		        print(f'{self.name}运行结束')
		
		obj = MyThread('LebronJames')
		obj.start()
		print('主线程')

		'''两个输出结果: LebronJames正在运行 主线程 LebronJames运行结束!!!'''

三、 多线程实现TCP服务端并发

		比多进程更加简单方便 消耗的资源更少
		
		Server:
				import socket
				from threading import Thread		# 导入模块
				
				server = socket.socket()
				server.bind(('127.0.0.1', 8080))
				server.listen(5)					# 设置端口 
				
				def talk(sock):		# 设置一个函数 接收数据 发送数据
				    while True:
				        data = sock.recv(1024)		
				        print(data.decode('utf8'))
				        sock.send(data.upper())
				
				while True:
				    sock, addr = server.accept()		
				    p = Thread(target=talk, args=(sock,))	 # 开设进程去完成数据交互
				    p.start()

		Clinet:
				import socket
				
				client = socket.socket()
				client.connect(('127.0.0.1', 8080))			# 设置固定的地址
				
				while True:
				    client.send(b'hello baby')				# 发送数据
				    data = client.recv(1024)
				    print(data.decode('utf8'))

四、 Join方法

		主线程等到子线程运行结束之后再运行(跟主线程一个道理)
		
		from threading import Thread
		import time
		
		def task():
		    print('正在执行')
		    time.sleep(3)
		    print('运行结束')
		
		t = Thread(target=task)
		t.start()
		t.join()
		print('主线程')			# 输出结果 : 正在执行 运行结束 主线程

五、 同一个进程下线程数据共享

		from threading import Thread

		money = 1000
		
		def func():
		    global money			# 同一个进程下 线程之间数据共享 
		    money = 666
		
		t = Thread(target=func)
		t.start()					
		t.join()  # 确保线程运行完毕 再查找money 结果更具有说服性
		print(money)			# 输出结果: 666

六、 线程对象相关方法

		1. 进程号
			同一个进程下开设的多个线程拥有相同的进程号
		2.线程名
			需要使用到模块 from threading import Thread, current_thread
			current_thread().name 
			主:MainThread	子:Thread-N
		3. 进程下的线程数 模块 active_count
			active_count()
		from threading import Thread, current_thread, active_count
		import os
		
		money = 1000
		
		def func():
		    global money
		    money = 666
		    print('子线程名', current_thread())
		
		t = Thread(target=func)
		t.start()
		t.join()  # 确保线程运行完毕 再查找money 结果更具有说服性
		
		print('子进程', os.getpid())
		print('进程下的线程数',active_count())

		输出结果:
			子线程名 <Thread(Thread-1, started 13071642624)>
			子进程 3233
			进程下的线程数 1

七、 守护线程

		守护线程伴随着被守护的线程的结束而结束
		进程下所有的守护线程 主线程(主进程)结束 所有线程结束全部直接结束
		进程下所有的非守护线程结束 主线程(主进程)才能真正结束!!!(没有被守护的结束了主线程才结束)
		from threading import Thread
		import time
		
		def task():
		    print('子线程运行task函数')
		    time.sleep(3)
		    print('子线程运行task结束')
		
		t = Thread(target=task)
		t.daemon = True		# 伴随主线程 主线程结束子进程也结束
		t.start()
		# t.daemon = True	# 不能放在start下面 否则报错!
		print('主线程')

		输出结果 : 子线程运行task函数 主线程

八、 GIL全局解释器锁

		储备知识:
			1.python解释器也是由编程语言写出来的
				Cpython 用C写出来的	Jpython 用Java写出来的 Pypython 用python写出来的
			2.GIL的研究是Cpython解释器的特点 不是python语言的特点
			3.GIL本质也是一把互斥锁
			4.GIL的存在使得同一个进程下的多个线程无法同时执行(关键)
				言外之意:单进程下的多线程无法利用多核优势 效率低!!!
		误解:
			1.python的多线程就是垃圾 利用不到多核优势
				python的多线程确实无法使用多核优势 但是在IO密集型的任务下是有用的
			2.既然有GIL 那么以后我们写代码都不需要加互斥锁
				不对 GIL只确保解释器层面数据不会错乱(垃圾回收机制)
				针对程序中自己的数据应该自己加锁处理

技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点点赞收藏+关注 谢谢支持!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LoisMay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值