[TOC]

多任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#coding=utf-8

from time import sleep

def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)

def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)

if __name__ == '__main__':
sing() #唱歌
dance() #跳舞
正在唱歌...0
正在唱歌...1
正在唱歌...2
正在跳舞...0
正在跳舞...1
正在跳舞...2

很显然刚刚的程序并没有完成唱歌和跳舞同时进行的要求

如果想要实现“唱歌跳舞”同时进行,那么就需要一个新的方法,叫做:多任务

多任务的概念

在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?

答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。

真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。

注意:

  • 并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)

  • 并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的

线程

python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用

使用threading模块

单线程执行

1
2
3
4
5
6
7
8
9
10
#coding=utf-8
import time

def saySorry():
print("吃饭了吗?")
time.sleep(1)

if __name__ == "__main__":
for i in range(5):
saySorry()
吃饭了吗?
吃饭了吗?
吃饭了吗?
吃饭了吗?
吃饭了吗?

多线程执行

1
2
3
4
5
6
7
8
9
10
11
12
#coding=utf-8
import threading
import time

def saySorry():
print("我错了吗?")
time.sleep(1)

if __name__ == "__main__":
for i in range(5):
t = threading.Thread(target=saySorry)
t.start() #启动线程,即让线程开始执行
我错了吗?
我错了吗?我错了吗?

我错了吗?
我错了吗?
说明
  • 可以明显看出使用了多线程并发的操作,花费时间要短很多
  • 当调用start()时,才会真正的创建线程,并且开始执行

主线程会等待所有的子线程结束后才结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#coding=utf-8
import threading
from time import sleep,ctime

def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)

def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)

if __name__ == '__main__':
print('---开始---:%s'%ctime())

t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)

t1.start()
t2.start()

#sleep(5) # 屏蔽此行代码,试试看,程序是否会立马结束?
print('---结束---:%s'%ctime())
---开始---:Thu Jul  9 21:28:57 2020
正在唱歌...0
正在跳舞...0---结束---:Thu Jul  9 21:28:57 2020

正在唱歌...1正在跳舞...1

正在跳舞...2正在唱歌...2

查看线程数量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#coding=utf-8
import threading
from time import sleep,ctime

def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)

def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)

if __name__ == '__main__':
print('---开始---:%s'%ctime())

t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)

t1.start()
t2.start()

while True:
length = len(threading.enumerate())
print('当前运行的线程数为:%d'%length)
if length<=6:
break

sleep(0.5)
---开始---:Thu Jul  9 21:32:44 2020
正在唱歌...0
正在跳舞...0当前运行的线程数为:7

当前运行的线程数为:7
正在唱歌...1
正在跳舞...1当前运行的线程数为:7

当前运行的线程数为:7
正在唱歌...2
正在跳舞...2
当前运行的线程数为:7
当前运行的线程数为:7
当前运行的线程数为:5