Threading学会多线程Python

https://www.bilibili.com/video/BV1jW411Y7Wj?p=3&vd_source=d59d7bc22106d87da35c63b8af6491e8

什么是多线程?

thread 可以让python在同一时间去做很多东西,大大节省了计算机计算的时间。

添加线程 add thread

import threading

def thread_job():
	print("This is an added Thread, number is %s" % threading.current_thread)	# 将当前线程的名称打印出来

def main():
	print(threading.active_count())	# 现在有多少个激活了的线程
	print(threading.enumerate())	# 具体是哪几个呢
	print(threading.current_thread())	# 当前线程
	
	added_thread = threading.Thread(target=thread_job)	# 添加一个线程,并给入任务
	added_thread.start()	# 真正执行线程


if __name__ == '__main__':
	main()
	

join 功能

import threading

def thread_job():
	print('T1 start\n')
	for i in range(10):
		time.sleep(0.1)
	print('T1 finish\n')

def main():
	added_thread = threading.Thread(target=thread_job, name='T1')	# 添加一个线程,并给入任务,命名线程名字为T1
	added_thread.start()	# 真正执行线程
	print('all done\n')


if __name__ == '__main__':
	main()

**加粗样式**

多线程是同时在进行的一个线程任务
如果你想等待所有线程运行完之后,然后再开始其他命令,就会用到join

import threading

def thread_job():
	print('T1 start\n')
	for i in range(10):
		time.sleep(0.1)
	print('T1 finish\n')

def main():
	added_thread = threading.Thread(target=thread_job, name='T1')	# 添加一个线程,并给入任务,命名线程名字为T1
	added_thread.start()	# 真正执行线程
	added_thread.join()
	print('all done\n')


if __name__ == '__main__':
	main()

在这里插入图片描述

import threading

def thread_job():
	print('T1 start\n')
	for i in range(10):
		time.sleep(0.1)
	print('T1 finish\n')


def T2_job():
	print('T2 start\n')
	print('T2 finish\n')


def main():
	added_thread = threading.Thread(target=thread_job, name='T1')	# 添加一个线程,并给入任务,命名线程名字为T1
	thread2 = threading.Thread(target=T2_job, name='T2')
	added_thread.start()	# 真正执行线程
	thread2.start()
	added_thread.join()
	print('all done\n')


if __name__ == '__main__':
	main()

假如没有join
在这里插入图片描述
added_thread.join()
在这里插入图片描述

thread2.join()
在这里插入图片描述

thread2.join() && add_thread.join()
在这里插入图片描述

Queue 功能

多线程所要摄取的功能是没有返回值的,所以我们要把它运算出来的结果放到一个长的队列中,对于每个线程的队列到了主线程再拿出来,进行计算。

import threading
import time 
from queue import Queue

def job(l, q):
	for i in range(len(l)):
		l[i] = l[i] ** 2
	q.put(l)


def multithreading():
	q = Queue()
	threads = []
	data = [ [1, 2, 3], [3, 4, 5] , [4, 4, 4], [5, 5, 5] ]
	for i in range(4):
		t = threading.Thread(target=job, args(data[i], q)
		t.start()
		threads.append(t)
	for thread in threads:
		thread.join()
	results = []
	for _ in range(4):
		results.append(q.get())	# 从q中按顺序拿出一个
	print(results)	

if __name__ == '__main__'
	multithreading()

在这里插入图片描述

不一定有效率 GIL

多线程有个全局控制,并不是把任务平均分给每个人。
它其实是有个GIL(Global Interpreter Lock),全局解释器锁
为了实现多线程功能,其实是让程序把这个线程锁住,Python只能让一个线程在同一时间运算,其实是在不断切换,看似多线程

import threading
import time
import copy
from queue import Queue

def job(l, q):
    res = sum(l)
    q.put(res)

def multithreading(l):
    q = Queue()
    threads = []
    for i in range(4):
        t = threading.Thread(target=job, args=(copy.copy(l),q),name='T%i'%i)
        t.start()
        threads.append(t)
    [t.join() for t in threads]
    total = 0
    for _ in range(4):
        total += q.get()
    print(total)


def normal(l):
    total = sum(l)
    print(total)


if __name__ == '__main__':
    l = list(range(1000000))
    s_t=time.time()
    normal(l*4)
    print('normal:',time.time()-s_t)
    s_t=time.time()
    multithreading(l)
    print('multithreading:',time.time()-s_t)

在这里插入图片描述
如果一个线程负责发送,另外一个线程负责接收,效率会提高很多。

如果是要处理数据,多线程可能帮不上我们的忙

python中因为GIL的存在,多线程适合IO密集型,多进程适合运算密集型

因为每一个核是有单独的逻辑的空间,不会受GIL的影响

锁 lock

如果你想第一个线程先处理完数据得到一个初步的结果,再拿去给第二个线程处理的话。
你可能要用到锁的功能,先锁住第一个线程,等它处理完,再运行第二个线程。

import threading

def job1():
	global A, lock
	lock.acquire()	# 开启 lock
	for i in range(10):
		A += 1
		print('job1', A)
	lock.release()	# 关闭 lock


def job2():
	global A, lock
	lock.acquire()
	for i in range(10):
		A += 10
		print('job2', A)
	lock.release()


if __name__ == '__main__':
	lock = threading.Lock()
	A = 0
	t1 = threading.Thread(target=job1)
	t2 = threading.Thread(target=job2)
	t1.start()
	t2.start()
	t1.join()
	t2.join()

注意

如果程序卡死在一个线程中。根据官方文档的实现,在Windows中,Ctrl+C是无法触发KeyboardInterrupt中断的;而在Linux中是可以的。

一个进程的结束并不依赖于线程的完成。

解决
面临问题:主线程被堵塞
原因:没有办法被 interrupt 了
join:函数是可以给一个 timeout 函数的,就是最多等多少秒。所以可以在timeout之后,去检查这个程序是否结束了。

  import threading
  import time

class Test(threading.Thread):
	def run(self):
		while True:
			time.sleep(0.5)

t = Test()
t.daemon = True	# 解决线程Exception,进程却没有退出的问题
t.start()
while t.is_alive():
	t.join(timeout=1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Harvey2001

感谢您的认可,无限飓风不断进步

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

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

打赏作者

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

抵扣说明:

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

余额充值