python多线程

一。基本概念:

1.线程:

线程又称为轻量级进程,线程之间可以进行信息共享,线程可以看成是主进程或‘主线程’的迷你进程。

2.进程:

进程又称为重量级进程,进程之间是独立的,进程间共享信息要通过 ‘进程间通信(IPC)’ 来进行。

3.同步:

同步是指一个任务执行完成后,另一个任务接着进行,就是一个挨着一个,比如你在食堂打饭,一号窗口的菜好吃,有很多人排队,只有前一个打完饭,后一个才可以打饭。

4.异步:

异步是指多个任务同时进行,比如:食堂有很多打饭窗口,很多人可以同时进行打饭。

  1. I/O:

I/O是 input/output 的缩写,代表的含义是读写。

  1. I/O密集型代码(I/O bound):

I/O密集型是指程序进行读写操作要很多,计算相对较少。

  1. 计算密集型代码(CPU bound):

计算密集型是指程序主要进行计算,而读写操作要少。

  1. 并发和并行:

并发 CPU数量<线程数,并发是指相同时间间隔内执行任务。

并行 CPU数量>线程数,并行是指多个任务同时执行。

二。python和线程:

python代码的执行由python虚拟机(解释器主循环)来进行控制。

Python还有一个GIL(全局解释器锁),用来控制程序只有一个线程在执行。

GIL锁执行过程:

锁定

执行

释放

返回第一步。

python执行多线程时,其实是在相同时间间隔内对任务进行执行,每个任务执行一小段时间,然后挂起,在执行下一个,一直到最后一个,然后在从第一个开始,如此往复,直至结束。

python对于I/O密集型比计算密集型要友好。原因:python在执行I/O密集型程序时,主要进行文件读写,而计算较少,每个任务在计算的同时可以进行对其他以完成的计算读写,而计算密集型对于计算较多,一直占用CPU,导致处理效率不高,所以对于计算密集型并不友好。

三。threading模块

对于多线程有thread模块和threading模块。thread模块在执行多线程时,在不加锁的情况下,如果主线程结束,而子线程还未结束时,子线程会被强制停止,造成得不到运行结果。在进行多线程学习时推荐使用threading模块。

1.添加线程: threading.Thread(target=函数名,args=(需要传入的参数))

Thread类还可以传入name,给线程命名。

2.判断线程是否激活状态: is_alive()

3.获取线程数量: threading.active_count()

4.获取当前线程:threading.current_thread()

5.获得线程名字:.name

6.等待线程:。join()

等待与不等待:

等待:

复制代码
1 def a_1():
2 print(‘aaaaa’)
3 time.sleep(3)
4 print(‘aaaaa’)
5 def a_2():
6 print(‘bbbbb’)
7 time.sleep(5)
8 print(‘bbbbb’)
9 def main():
10 print(’…start…’)
11 t1 = threading.Thread(target=a_1)
12 t2 = threading.Thread(target=a_2)
13 t1.start()
14 t2.start()
15 print(’…end…’)
16
17 if name == ‘main’:
18 main()
19
20
21 运行结果:
22
23 …start…
24 aaaaa
25 bbbbb
26 …end…
27 aaaaa
28 bbbbb
29
30 Process finished with exit code 0
复制代码
从运行结果可以看出,在不添加等待时,运行结果并不是我们想要的结果。

下面是不用 .join()的等待:

复制代码
def main():
print(’…start…’)
t1 = threading.Thread(target=a_1)
t2 = threading.Thread(target=a_2)
t1.start()
t2.start()
time.sleep(8)
print(’…end…’)

if name == ‘main’:
main()

运行结果:
…start…
aaaaa
bbbbb
aaaaa
bbbbb
…end…

Process finished with exit code 0
复制代码
通过添加time.sleep()语句使主线程等待子线程运行结束再运行下一步操作。打印内容均在…start…和…end…之间。

下面是运用 .join()进行等待。

def main():
print(’…start…’)
t1 = threading.Thread(target=a_1)
t2 = threading.Thread(target=a_2)
t1.start()
t2.start()
t1.join()
t2.join()
print(’…end…’)

if name == ‘main’:
main()

运行结果:
…start…
aaaaa
bbbbb
aaaaa
bbbbb
…end…

Process finished with exit code 0
通过该结果可以看出,添加sleep()和join()效果一样,但是推荐使用.join() ,因为在运行程序的时候用sleep()等待,还得知道等待时间,比较麻烦。join()较为方便。

创建线程方法:

<1> 给Thread类传入函数

<2>给Thread类传入一个实例类

<3>创建一个子类,继承Thread类,然后将函数传入子类中

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

在不用多线程时:

import datetime
def num_1():
print(‘start…1’)
time.sleep(2)
print(‘end…1’)
def num_2():
print(‘start…2’)
time.sleep(4)
print(‘end…2’)

def main():
a = datetime.datetime.now()
print(’…start…’)
num_1()
num_2()
print(’…end…’)
b = datetime.datetime.now()
p = (b - a).seconds
print('运行%s秒 ’ % p)
if name == ‘main’:
main()
创建两个函数,分别打印不同内容,并在程序执行完成打印执行时间。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

对于<1>

下面是示范代码: .join()是主线程等待子线程完成后在执行下一步操作。

复制代码
1 import threading
2 import datetime
3 #传递函数(1)
4 def num(nu,se):
5 print(’%s start’ % nu)
6 time.sleep(se)
7 print(’%s end’ % nu)
8
9 time_list = [2,4]
10 def main():
11 a = datetime.datetime.now()
12 print(’…start…’)
13 thread_list = []
14 for x in range(len(time_list)):
15 t = threading.Thread(target=num,args=(x,time_list[x]))
16 thread_list.append(t)
17 for x in thread_list:
18 x.start()
19 for x in thread_list:
20 x.join()
21 print(’…end…’)
22 b = datetime.datetime.now()
23 p = (b - a).seconds
24 print(‘运行%s秒’ % p)
25 if name == ‘main’:
26 main()
复制代码

<2>添加一个实例类。

复制代码
class New_1():
def init(self,num,se):
self.num = num
self.se = se
def call(self):
return self.num(*self.se)
pass

def main():
a = datetime.datetime.now()
print(’…start…’)
thread_list = []
for x in range(len(time_list)):
t = threading.Thread(target=New_1(num,(x+1,time_list[x])))
thread_list.append(t)
for x in thread_list:
x.start()
for x in thread_list:
x.join()
print(’…end…’)
b = datetime.datetime.now()
p = (b-a).seconds
print(‘运行%s秒’ % p)

if name == ‘main’:
main()
运行结果:
…start…
1 start
2 start
1 end
2 end
…end…
运行4秒

Process finished with exit code 0

复制代码
3.继承Thread类,将内容传递进子类中。

下面是代码:
#传递函数(1)
def num(nu,se):
print(’%s start’ % nu)
time.sleep(se)
print(’%s end’ % nu)
time_list = [2,4]
class New_2(threading.Thread):
def init(self,num,se):
super().init()
self.num = num
self.se = se
#对于下面的函数run()进行重写,可以灵活的定义函数,函数名必须是run(),否则在传入参数后运行时,不会运行多线程。
def run(self):
return self.num(*self.se)
pass

def main():
a = datetime.datetime.now()
print(’…start…’)
thread_list = []
for x in range(len(time_list)):
t = New_2(num,(x,time_list[x]))
thread_list.append(t)
for x in thread_list:
x.start()
for x in thread_list:
x.join()
print(’…end…’)
b = datetime.datetime.now()
p = (b-a).seconds
print(‘运行%s秒’ % p)
if name == ‘main’:
main()

运行结果:
…start…
0 start
1 start
0 end
1 end
…end…
运行4秒

Process finished with exit code 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值